应用调试(五)侵入式SWI
title: 应用调试(五)侵入式SWI
date: 2019/01/19 21:27:31
toc: true
应用调试(五)侵入式SWI
场景应用
- 反汇编源程序,查看汇编代码,然后直接修改二进制的bin文件,替换其中一条A指令为B指令,B指令是swi跳转指令
- 构造一个
SWI
跳转,加入到内核中,这个SWI跳转可以用来打印变量等,然后完成原来A指令需要完成的事情 - 直接运行修改后的文件,也就是说程序执行到A指令时,先去执行内部的SWI跳转,然后执行A指令
- 整个过程实际上和我们调试的软件断点是很像的
为什么需要这么调试?不直接修改APP程序更方便?
这个应用我个人觉得应该是破解程序用的,不然修改APP多省事,或者直接弄个驱动能够操作内核,APP去调用这个驱动函数就好了.
应该是有个APP,那么这个时候我们只有执行程序,没有源代码,我们就可以大概看下想破解什么的,,如果直接加入代码的话,有些地址相关的指令可能就不对的,这种直接替换的方式,也不会破坏地址空间.
但是 破解应该有更好的工具,暂时没想到有什么绝佳的用处.
测试程序
这里写一个正常的测试程序如下,这里使用了sleep
是因为直接快速打印,估计缓存区有优先级后两个不同的进程打印不一致
#include <stdio.h>
#include <unistd.h>
int cnt = 0;
void C(void)
{
int i = 0;
while (1)
{
printf("Hello, cnt = %d, i = %d\n", cnt, i);
cnt++;
i = i + 2;
sleep(5);
}
}
void B(void){C();}
void A(void){B();}
int main(int argc, char **argv)
{
A();
return 0;
}
现在假设我们需要在i = i+ 2;
这里设置断点,因为这个汇编语句简单,反汇编文件
000084c0 <C>:
84c0: e1a0c00d mov ip, sp
84c4: e92dd800 stmdb sp!, {fp, ip, lr, pc}
84c8: e24cb004 sub fp, ip, #4 ; 0x4
84cc: e24dd004 sub sp, sp, #4 ; 0x4
....
84fc: e5823000 str r3, [r2]
8500: e51b3010 ldr r3, [fp, #-16] ;这里获取局部变量i的值
8504: e2833002 add r3, r3, #2 ; 0x2 ;这个就是i=i+2
...
修改APP的bin
修改为SWI指令,可以参考上一节的汇编,或者看下SWI的指令格式
// 上一节的指令格式如下
84b8: ef900160 swi 0x00900160
所以 也就是修改二进制文件中的e2833002
为ef900160
,注意下小端模式低字节在低地址也就是搜索02 30 83 e2
替换为60 01 90 ef
修改SWI
在上一个小结的基础上修改sys_hello
,在fs/read_write.c
查看下全局变量
cnt
,我们可以在dis中查看cnt的地址000107c8 <cnt>:
107c8: 00000000 andeq r0, r0, r0
局部变量的值怎么看? 看到汇编i的运算,也就是存在
[fp-16]
中8500: e51b3010 ldr r3, [fp, #-16] ;这里获取局部变量i的值
8504: e2833002 add r3, r3, #2 ; 0x2 ;替换指令在这里
接下来我们打印全局变量cnt
和局部变量i
,这里看下汇编知道是r3
asmlinkage void sys_hello(char __user * buf, size_t count)
{
int val;
struct pt_regs *regs;
/* 1.输出一些调试信息 */
/* 这里我们输出应用程序中的cnt值,在反汇编文件test_sc.dis中搜cnt的cnt的地址为0x00010788 */
copy_from_user(&val, (const void __user *)0x000107c4,4);
printk("sys_hello : cnt = %d \n",val);
/* 2. 执行被替代的指令 */
regs = task_pt_regs(current);
regs->ARM_r3 += 2;
/* 获得应用程序中C函数局部变量i的值 */
copy_from_user(&val,(const void __user *)(regs->ARM_fp - 16),4);
printk("sys_hello : i = %d \n",val);
/* 3. 返回 */
}
获得当前进程的寄存器
上述的例子中需要获得寄存器的值,使用task_pt_regs(current)
可以获得当前进程的寄存器值.当前进程就是发生swi
前应用程序的进程。
regs = task_pt_regs(current);
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
测试运行
可以看到SWI
中打印出来了全局变量cnt
,因为函数是先打印cnt
,然后cnt+1
,所以SWI
的cnt
比app
打印的大1
,局部变量i
是app
打印后swi
打印,然后+2
,所以app
的比swi
的i
一致
# chmod +x test_sc_sleep_swi
# ./test_sc_sleep_swi
Hello, cnt = 0, i = 0
sys_hello : cnt = 1
sys_hello : i = 0
######################################
# 系统调用cnt 比app的大1,与上一次的i值相同
#####################################
###↓↓↓↓ 接下去是第二轮
Hello, cnt = 1, i = 2
sys_hello : cnt = 2
sys_hello : i = 2
Hello, cnt = 2, i = 4
sys_hello : cnt = 3
sys_hello : i = 4
Hello, cnt = 3, i = 6
sys_hello : cnt = 4
sys_hello : i = 6
恢复代码 进程间内存拷贝
代码是放在内存里的,我们可以在执行一段时间后恢复这段代码,可以看到指令地址在0x8504
这里使用了函数access_process_vm
来将当前进程的一段内存内容拷贝到另一个进程的内存中
// 8504: e2833002 add r3, r3, #2 ; 0x2 ;替换指令在这里
static int cnt = 0;
int ret;
if (++cnt == 5)
{
copy_from_user(&val, (const void __user *)0x8504, 4);
printk("[0x8504] code = 0x%x\n", val);
printk("regs->ARM_lr = 0x%x\n", regs->ARM_lr);
val = 0xe2833002; //原来正确的代码
ret = access_process_vm(current, 0x8504, &val, 4, 1);
printk("access_process_vm ret = %d\n", ret);
cnt = 0;
}
接着测试下是否生效,确实5次后就不再打印sys_hello
# mount -t nfs -o nolock,vers=2 192.168.95.222:/home/book/stu /mnt
# /mnt/code/test_sc_sleep_swi
Hello, cnt = 0, i = 0
sys_hello : cnt = 1
sys_hello : i = 0
Hello, cnt = 1, i = 2
sys_hello : cnt = 2
sys_hello : i = 2
Hello, cnt = 2, i = 4
sys_hello : cnt = 3
sys_hello : i = 4
Hello, cnt = 3, i = 6
sys_hello : cnt = 4
sys_hello : i = 6
Hello, cnt = 4, i = 8
sys_hello : cnt = 5
sys_hello : i = 8
[0x8504] code = 0xef900160
regs->ARM_lr = 0x84ec
access_process_vm ret = 4
#####下面不再打印sys_hello了
Hello, cnt = 5, i = 10
Hello, cnt = 6, i = 12
TODO 更多参考文献
下面的文章没怎么仔细看,先放在这里等以后水平上来了再瞅瞅,标记下 @Todo
应用调试(五)侵入式SWI的更多相关文章
- MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式
MVC的验证(模型注解和非侵入式脚本的结合使用) @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...
- 使用phpAnalysis打造PHP应用非侵入式性能分析器
使用phpAnalysis打造PHP应用非侵入式性能分析器,查找PHP性能瓶颈. 什么是phpAnalysis phpAnalysis是一款轻量级非侵入式PHP应用性能分析器,适用于开发.测试及生产环 ...
- 支付宝开源非侵入式 Android 自动化测试工具 Soloπ
Soloπ(SoloPi)是支付宝开源的一个无线化.非侵入式的Android自动化测试工具,公测版拥有录制回放.性能测试.一机多控三项主要功能,能为测试开发人员节省宝贵时间. 本文是SoloPi团队关 ...
- BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)
开发者博客: BlockCanary — 轻松找出Android App界面卡顿元凶 开源代码:moduth/blockcanary BlockCanary对主线程操作进行了完全透明的监控,并能输出有 ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(三)
Android沉浸式(侵入式)标题栏(状态栏)Status(三) 从附录文章1,2可以看到,依靠Android系统提供的标准方案,状态栏即便在透明状态下,仍然有些半透明而不是全透明.本文是And ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(二)
Android沉浸式(侵入式)标题栏(状态栏)Status(二) 附录1以xml写style实现了Android沉浸式(侵入式)状态栏(标题栏),同样以上层Java代码实现.在附录文章1的基础上 ...
- Android沉浸式(侵入式)标题栏(状态栏)Status(一)
Android沉浸式(侵入式)标题栏(状态栏)Status(一) 现在越来越多的APP设计采用这种称之为沉浸式状态栏(Status)的设计,这种沉浸式状态栏又称之"侵入式"状 ...
- C++侵入式链表
C++标准模板库中的list是非侵入式的链表,当我们通过对象来删除容器中的对象时,需要从头到尾查找一次得到iterator,最后通过iterator来删除对象.这样删除容器中的对象时比较缓慢,所以就实 ...
- Hook 无侵入式埋点(页面统计)
一.技术原理 Method-Swizzling 黑魔法 方法交换(不懂的可以查) 二.页面统计 某盟页面统计SDK需要开发者在APP基类里实现ViewDidAppear和viewDidDisappea ...
随机推荐
- MPP架构海量数据分析仓库——Greenplum介绍
一.Greenplum背景 时间回到2002年,互联网行业经过近10年的发展,数据量正处于快速增长期: 1.传统的主机计算模式在海量数据面前,除了造价昂贵外,在CPU计算和IO吞吐上不能满足海量数据的 ...
- 【eclipse】mybatis配置文件创建与mapper接口文件创建
什么是mybatis: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. mybatis配置文件: <?xml version="1.0" ...
- win10 系统 wifi自动断开连接 wifi热点不稳定
我的系统的电脑是win10系统,笔记本 下载了一个wifi共享大师,但是wifi总是自动断,于是就找了找问题所在 在网上看了许多方案,大多数都是 在 电源管理 把[允许计算机关闭此设备以节 ...
- GitHub下载克隆clone指定的分支tag代码
需求描述: 这边有很多tag分支版本的代码,我想克隆下载指定版本到我服务器上面 例如:我想下载tag:1.4.1的代码 解决方法: 命令:git clone --branch [tags标签] [gi ...
- 抖音、YouTube、Facebook等新媒体营销与运营相关14本书
最近几年看过的抖音等新媒体营销与运营相关的书有14本,好书不多.具体清单整理如下,点击标题或图片可以看详细点评与内容摘抄: 4星|<屏幕上的聪明决策>:人在手机/电脑上做选择的心理学研究综 ...
- IDEWorkspaceChecks.plist文件是干什么用的?
在提交PR的时候,无意间发现了在xcworkspace/xcshareddata中多了一个名为IDEWorkspaceChecks.plist的文件.自己并没有手动创建此文件,在网上查了一下,最终对其 ...
- Spring boot admin 节点状态一直为DOWN的排查
项目中需要监控各个微服务节点的健康状态,找到了spring boot admin这个全家桶监控工具,它其实是Vue.js美化过的Spring Boot Actuator,官方的解释是: codecen ...
- git如何设置ssh密钥
git设置ssh密钥 目前git支持https和git两种传输协议,github分享链接时会有两种协议可选: 1.Clone with SSH 2.Clone with HTTPS git在使用htt ...
- Python开发【第一篇】基础题目一
1.求1-2+3-4+5.....99的所有数的和 n = 1 s = 0 while n<100: temp = n%2 if temp == 0: #偶数 s = s-n else: s = ...
- 使用springMVC时的web.xml配置文件
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" " ...