简介

taskverse是《linux二进制分析》一书作者编写的一个隐藏进程的检测工具,它使用/proc/kcore来访问内核内存,github的地址在这里:https://github.com/elfmaster/taskverse。

/proc/kcore

这个文件是内核提供的用来遍历内核内存的接口,使用elf文件格式,他的实现在内核文件\fs\proc\kcore.c中,文件的主要操作在proc_kcore_operations中,围绕一个链表kclist_head来组织elf中的各个段。而一个段就代表着一段内存,将这些内存映射成可执行文件的段。看看这些段的信息,在这之前有一个note段,这里面保存着一些其他信息,这里就不分析了,从内核源码里的get_kcore_size可以看出网note段里面放的是什么。

为了解释这个文件的用法,我写了一个简单的例子,代码在这里:https://github.com/smakk/kocre_sample

可以使用readelf -h的命令去查看,可以发现/proc/kcore这个文件是没有节区的,也就是没有办法访问到符号表,这里使用了/proc/kallsyms这个文件来访问符号地址,具体代码如下,根据名字,不断读取符号文件来找到符号地址

//由于/proc/kcore没有节头,找不到符号表,所以通过kallsym来找符号地址
unsigned long get_sym(char* name){
FILE *fd;
char symbol_s[];
int i;
unsigned long address;
char tmp[], type; if ((fd = fopen("/proc/kallsyms", "r")) == NULL)
{
printf("fopen /proc/kallsym wrong\n");
exit(-);
}
while(!feof(fd))
{
if(fscanf(fd, "%lx %c %s", &address, &type, symbol_s)<=){
printf("fscanf wrong\n");
exit(-);
}
if (strcmp(symbol_s, name) == )
{
fclose(fd);
return address;
}
if (!strcmp(symbol_s, ""))
break;
}
fclose(fd);
return ;
}

接着就是/proc/kcore的使用,这里使用一个全局的链表kcore,来表示/kcore的一个段信息中的虚拟地址,文件偏移量和大小,有这3个量就可以访问内存了

struct kcore_list{
struct kcore_list* list;
unsigned long vaddr;
unsigned long offset;
size_t size;
};
struct kcore_list kcore; /*
生成kcore链表,按照虚拟地址升序存放kcore提供的所有的地址空间,而且这些地址空间是不重叠的
*/
void* init_kcore_list(){
int fd = open("/proc/kcore", O_RDONLY);
if(fd < ){
printf("open /proc/kcore wrong\n");
exit(-);
}
Elf64_Ehdr head;
read(fd,&head,sizeof(Elf64_Ehdr));
if(lseek(fd,head.e_phoff,SEEK_SET)<){
printf("lseek /proc/kcore wrong\n");
exit(-);
}
Elf64_Phdr phdr[head.e_phnum];
read(fd,&phdr,sizeof(Elf64_Phdr)*head.e_phnum);
close(fd);
int i;
for(i=;i<head.e_phnum;i++){
struct kcore_list* k_list = malloc(sizeof(struct kcore_list));
k_list->vaddr = phdr[i].p_vaddr;
k_list->offset = head.e_phoff+sizeof(Elf64_Phdr)*i;
k_list->size = phdr[i].p_memsz;
struct kcore_list* tmplist = &kcore;
while(tmplist->list != NULL && tmplist->list->vaddr<k_list->vaddr){
tmplist = tmplist->list;
}
k_list->list = tmplist->list;
tmplist->list = k_list;
//printf("%lx\n",k_list->vaddr);
}
return;
}

现在已经存储完kcore的段信息,要想访问符号虚拟地址指向处的地址,就是要先找出虚拟地址位于哪个段中,然后转换成这个段在文件中的偏移,最终根据文件偏移去访问文件。代码如下:

/*
根据虚拟地址addr,从/proc/kcore这个位置读取size大小的内存
*/
void* get_area(unsigned long addr, size_t size){
void* ret;
struct kcore_list* k_list = kcore.list;
while(k_list != NULL && addr>k_list->vaddr + k_list->size){
k_list = k_list->list;
}
if(addr>=k_list->vaddr && addr+size<k_list->vaddr + k_list->size){
int fd = open("/proc/kcore", O_RDONLY);
if(fd < ){
printf("open /proc/kcore wrong\n");
exit(-);
}
if(lseek(fd,k_list->offset+(addr-k_list->vaddr),SEEK_SET)<){
printf("lseek /proc/kcore wrong\n");
exit(-);
}
ret = malloc(size);
read(fd,ret,size);
close(fd);
}
return ret;
}

最后,使用这个借口,我做了一个简单的使用例子,找到init_task的进程描述符,在内核的进程描述符中,第一个字段表示的是进程状态,这里输出init_task的进程状态,打印这和结果。

int main(){
init_kcore_list();
printf("_text addrs is %lx\n",get_sym("_text"));
void * code = get_area(get_sym("init_task"),);
unsigned long * statue = (unsigned long *)code;
//0代表正在运行,大于0表示停止了
printf("init_task statue is %ld\n", *statue);
return ;
}

taskverse分析

程序入口地址在主目录下的taskverse.c中的mian函数,在taskverse中,可以使用两种寻找符号的方式,一种是kallsyms,另一种是systemmap文件。

沿着主函数,load_live_kcore函数去分析kcore文件,然后取出该文件的一些部分,存放形成一个Elf_t,在遍历段的过程中,作者关注了3个段,一个是文本段,一个是vmalloc使用的段,一个是kmalloc使用的段。地址分别是0xffff880100000000和0xffff880000100000,text段的起始地址放在_text符号的位置。

值得注意的是elf结构中的mem结构,这里的mem结构放了3个内容

1、elf头
2、程序头表
3、text段内容
后面从mem中取值的时候要注意,这里的地址计算
然后就开始获取符号地址,这里获取到init_task的位置,然后kcore_translate_kernel将它翻译为文件地址,最后从文件中读取task_struct结构的内容,遍历tasklist来获取到进程列表,然后和proc目录下的进程进行对比,如果发现不一样则是发现了隐藏进程。
 

taskverse学习的更多相关文章

  1. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  2. Angular2学习笔记(1)

    Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...

  3. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  4. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  5. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  6. Unity3d学习 制作地形

    这周学习了如何在unity中制作地形,就是在一个Terrain的对象上盖几座小山,在山底种几棵树,那就讲一下如何完成上述内容. 1.在新键得项目的游戏的Hierarchy目录中新键一个Terrain对 ...

  7. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  8. 菜鸟Python学习笔记第一天:关于一些函数库的使用

    2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...

  9. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

随机推荐

  1. Hive 参数

    hive.exec.max.created.files •说明:所有hive运行的map与reduce任务可以产生的文件的和 •默认值:100000  hive.exec.dynamic.partit ...

  2. 如何单独编译Linux内核的某个模块?

    1. 配置该模块为[M] 2. 编译 make modules SUBDIRS=./drivers/rtc (5.3的内核为make modules M=./drivers/rtc) 3. 安装 ma ...

  3. 关于OpenCL中三重循环的执行次序

    源自OpenGPU社区的一个帖子的讨论: 一个有意思的openCL问题

  4. OOM异常的发生原因

    一,jvm内存区域 1,程序计数器 一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. 2,java栈 与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存 ...

  5. Bootstarp学习

    Bootstarp中文网 http://www.bootcss.com/ https://v2.bootcss.com/javascript.html

  6. Eclipse部署时项目中依赖的jar包不能部署到服务器WEB-IN下lib目录

    转: Eclipse部署时项目lib下jar包不能部署到服务器WEB-IN下lib目录及Eclipse下tomcat服务器配置修改 2018年04月07日 11:04:19 拾悦酒吧 阅读数 1046 ...

  7. Queue class

    #pragma once#include <iostream>#include <iomanip> using namespace std; class Queue{ stru ...

  8. 依靠MySQL(frm、MYD、MYI)数据文件恢复

    该方法并不是适用于所有MySQL数据库 此次恢复是朋友那边的数据查不了了,请求我支援,出于各种心理原因,我答应试试,于是就有了这篇文章和这次经历,废话不多说.... 物理条件:宿机是Ubuntu16. ...

  9. django安装xadmin中出现的报错汇总

    报错一:ModuleNotFoundError: No module named 'django.core.urlresolvers' ModuleNotFoundError: No module n ...

  10. 图解 HTTP 笔记(五)——Web 服务器

    该章的主要内容是讲解与 HTTP 协作的 Web 服务器 一.用单台虚拟主机实现多个域名 基于虚拟主机的功能,可以只使用一台物理机实现多个域名的网站部署. 在互联网上,域名通过 DNS 域名解析系统可 ...