作者: Android开发网原创 时间: 2011-10-18

对于Android平台的安全问题凸显,Android123经过长期的分析研究就目前Android平台上Rootkit开发实现底层防火墙相关基础做简单的总结,Android的Rootkit和PC上的Linux Rootkit没有太大的区别,如果你有Linux内核相关知识或Win32下内核驱动开发知识阅读本文会轻松很多。

和Windows一样Android的Rootkit离不开底层的调用,在Win32上我们使用较低层的API有Native API,一般以Ring0中以Zw开头的函数居多,在Ring3中则为Nt开头的函数,比如任务管理器常用的NtQuerySystemInformation函数,它们的特点就是调用系统底层服务,我们叫做系统服务描述表SSDT,当然类似的还有系统服务中断向量表IDT。在Linux中我们获取本机API需要使用LKM加载内核模块,通过Hook技术可以轻松的替换原有API的入口点实现隐藏进程、端口,对于底层的系统服务来说,在Linux中使用系统服务调用表(Sys Call Table)中的函数来执行相关操作。Android从早期版本就是用了Linux 2.6以上的内核版本,获取sys call table偏移地址和我们早期在PC Redhat获取技术上有很大不同,挂上gdb慢慢分析吧,目前业界公认的方法就是通过swi中断来动态搜索系统调用表,这里我们直接给出代码

include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/init_task.h>
#include <linux/syscalls.h>

unsigned long* find_sys_call_table();

int init_module() {
printk("<1> Hello, kernel!\n");
unsigned long *sys_call_table = find_sys_call_table();

return 0;
}
void cleanup_module() {
printk("<1>I'm not offended that you"
"unloaded me. Have a pleasant day!\n");
}

unsigned long* find_sys_call_table()
{
//Address of the sofware interrupt (swi) handler in high vector ARM systems like Android
const void *swi_addr = 0xFFFF0008;

unsigned long* sys_call_table = NULL;
unsigned long* ptr = NULL;
unsigned long vector_swi_offset = 0;
unsigned long vector_swi_instruction = 0;
unsigned long *vector_swi_addr_ptr = NULL;

// Get the load pc instruction from the swi
memcpy(&vector_swi_instruction, swi_addr, sizeof(vector_swi_instruction));
printk(KERN_INFO "-> vector_swi instruction %lx\n", vector_swi_instruction);

// Read the offset from the swi adress where the handler pointer lives
vector_swi_offset = vector_swi_instruction & (unsigned long)0x00000fff;
printk (KERN_INFO "-> vector_swi offset %lx\n", vector_swi_offset);

// Get the pointer to the swi handler (offset is from the load instruction location + 2 words, due to ARM quirks)
vector_swi_addr_ptr = (unsigned long *)((unsigned long)swi_addr + vector_swi_offset + 8);
printk (KERN_INFO "-> vector_swi_addr_ptr %p, value %lx\n", vector_swi_addr_ptr, *vector_swi_addr_ptr);

/************
* Starting at the beginning of the handler, search for the sys_call_table address load
* This code is the result of the /arch/arm/kernel/entry-common.S file, starting at the line
* ENTRY(vector_swi). You'll see that there is always a zero_fp after saving register state
* before any function begins. It's a good "lighthouse" to search for to make sure
* you've entered the stack-frame-proper before looking for the sys_call_table pointer load
* instruction
************/

ptr=*vector_swi_addr_ptr;
bool foundFirstLighthouse = false;
unsigned long sys_call_table_offset = 0;

printk (KERN_INFO "-> ptr %p, init_mm.end_code %lx\n", ptr, init_mm.end_code);

// Don't search past the end of the code block. This is a dumb bound, I should be searching till I hit the
// equivalent of a ret in ARM, but I didn't feel like figuring it out since ARM doesn't have a ret instruction
while ((unsigned long)ptr < init_mm.end_code && sys_call_table == NULL)
{
// Find the zero_fp invocation (which translates into a load of zero into R11)
if ((*ptr & (unsigned long)0xffff0fff) == 0xe3a00000)
{
foundFirstLighthouse = true;
printk (KERN_INFO "-> found first lighthouse at %p, value %lx\n", ptr, *ptr);
}

// Search for the loading of the sys_call_table (in entry-common.S, given as "adr tbl, sys_call_table",
// which translates to an add and a ldr. The add loads the sys_call_table pointer)
if (foundFirstLighthouse && ((*ptr & (unsigned long)0xffff0000) == 0xe28f0000))
{
// Get the offset from the add that will contain the actual pointer
sys_call_table_offset = *ptr & (unsigned long)0x00000fff;
printk (KERN_INFO "-> sys_call_table reference found at %p, value %lx, offset %lx\n", ptr, *ptr,

sys_call_table_offset);

// Grab that damn pointer and get on with it!
sys_call_table = (unsigned long)ptr + 8 + sys_call_table_offset;
printk (KERN_INFO "-> sys_call_table found at %p\n", sys_call_table);
break;
}

ptr++;
}

return sys_call_table;
}

熟悉Linux内核的网友可能知道system.map中可以获取,但对于市场上各种Android固件来说,动态搜索更安全可靠些。

更多相关文章

  1. Android培训班(9)
  2. Android(安卓)dumpsys工具分析
  3. linux kernel suspend Resume
  4. Android(安卓)中文翻译:Build System Overview
  5. 内核版本与Android版本对应关系
  6. Android(安卓)系统启动
  7. android--系统jar包引用
  8. [置顶] Android(安卓)设置铃声分析
  9. [原]Android系统进程Zygote启动过程的源代码分析

随机推荐

  1. mount android yaffs image on ubuntu
  2. Android(安卓)TV自定义通用标题栏(组合控
  3. Android中 实现输入框搜索,清楚历史记录
  4. Android实现CoverFlow效果三
  5. one mail for difference between LOCAL_
  6. TelephonyManager
  7. Android文件读写包含SDCard
  8. Android(安卓)App怎样调用 Frameworks Bl
  9. android曲线图
  10. Android:获取屏幕分辨率方法汇总