简介

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 调优(一)coding调优

    本人认为hive是很好的工具,目前支持mr,tez,spark执行引擎,有些大公司原来封装的sparksql,开发py脚本,但是目前hive支持spark引擎(不是很稳定,建议Tez先),所以离线还是 ...

  2. oracle查询历史执行语句

    SELECT * FROM v$sqlarea WHERE PARSING_SCHEMA_NAME='GAVIN' and SQL_TEXT LIKE '%delete%' ORDER BY LAST ...

  3. 消灭WinRAR广告

    1. 问题描述 WinRAR每次弹出的广告真的令人厌烦至极,虽然软件公司也得恰饭,免费给你用总得看俩广告吧,但是像我这样经常用WinRAR的人来说广告弹出频率未免也太过分了.一开始还只是用火绒的弹窗拦 ...

  4. android studio的安装和配置及解决uiautomatorviewer报错

    参考博客:https://www.cnblogs.com/singledogpro/p/9551841.html 安装Android Studio 走了不少弯路,现在整理出来,仅当备忘使用. 首先要先 ...

  5. Django中的 返回json对象的方式

    在返回json对象的几种方式: 1 from django.shortcuts import render, HttpResponse # Create your views here. from d ...

  6. 前端js保存页面为图片下载到本地

    前端js保存页面为图片下载到本地 手机端点击下载按钮将页面保存成图片到本地 前端js保存页面为图片下载到本地的坑 html2canvas 识别 svg 解决方案 方案 html2canvas.js:可 ...

  7. OOM异常的发生原因

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

  8. 智能指针-共享式shared_ptr

    #include <iostream>#include <string>#include <vector>#include <memory> using ...

  9. BigDecimal数据的加 减 乘 除 N次幂运算 以及比较大小

    在实际开开发过程中BigDecimal是一个经常用到的类: 它可以进行大数值的精确却运算,下面介绍一下它的加-减-乘-除以及N次幂的操作操作 import java.math.BigDecimal; ...

  10. 按下F2编辑dxDBTreeView的节点

    在TdxDBTreeView控件的OnKeyDown事件中写入if Key = VK_F2 thenbegin  if DBTreeMain.DBSelected = nil then    Exit ...