【droEvent】 项目记录--update 2-15

 【droEvent】,其实这个项目就是apk cfg的一个改良版本,由于当初设计的时候比较匆忙,框架里面存在一些未解决的问题,比如对for,do-while,try-catch-switch,结构不能很好的 还原等,解析效率较慢等。

所以这次,就对他进行二次改进,对于设计架构中不合理的地方,也进行一个修正,目的是开发一个实用的,android 事件流还原系统。

droEvent 系统:不需要源程序的代码,只需要输入apk, 就能自动插桩获得重打包的apk,接着输入对应的log之后,就能够解析出该app不同事件背后执行过的函数,包括函数级与控制流级两重粒度的解析。


【——确立关键的三个算法模块: CFG 分块解析, Pathid Encode, Pathid decode

12-30: 其实三个算法是相关的,最终要的,是找到能够合适的对smali项目进行encode 和decode 的算法,这样cfg也水到渠成了。

【——较为具体确立算法,数据结构,执行流程; 最终还是选回了WPF+mindfusion】

1-4:

[+]  确立了较为具体的核心算法,参考论文并作了适当的修改。

----设定插桩编码算法,每个back_edge都爆出log,+重置 + 记录断点
【基本要点】
1/以入度边数插桩个数。
如,3条入度边:
那么三条边的插桩为:r = r*3+0(1,2)
2/在back_edge时,进行log + 重置 + 断点
【注意】:
返回的边的余数值不能是0, 否则当返回点出现断点的时候,值一直是0.

Algorithm 1. The probe instrumentation algorithm
Input: CFG f
 addP( f.entry, “r:=0”);		 //initialize
 foreach node n in f do:
 	int s = n.fanIn(); 			//s is the number of inedges of node n
 	if s > 1 then
 	int i = 0; 				//i is the count of inedges
 	foreach inedge e of n do:
		if inedge.isbackedge():		//output the circulate probe|breakpoint and set to 0
			addP(e, " output r|break ")
			addP(e, " r : = 0")
 		addP(e, “r:=r*s+i”); 		//insert probes		
 		i++;
 addP(f.exit, "output r"); 		//collect pathids

----设定解码算法
【要点】
1/根据除以入度边数的余数判断哪条边,根据得到的商获取新的probe r


Algorithm 2. PAP backwalk algorithm
/* backwalk starts from the end node to the start node to facilitate the use of breakpoints later */
Function backwalk
Input: probe r, CFG f, Node start, Node end
Output: the corresponding path
 Node curr node = end;
 int i;
 ArrayList<Node> p = new arrayList<Node>(); 		//p is used to record the path
 while (curr node! = start)|(r!=0) do:
 	i = r%curr_node.fanIn();
 	r = r/curr_node.fanIn();
 	p.append(curr_node);
 	curr node = pre(curr_node, i);
 p.append(start);
 Collections.reverse(p);
 return p;

/* The method “pre” returns node v, which satisfies that the prober=r*n+i is on edge (v,n) */
Function (pre)
Input: Node n, int i
Output: the corresponding node
 foreach edgev → n do
 	if probe( v, n).remainder == i then
 	//check the remainder of the probe on edge(v,n)
 	return v;

----断点解码
【要点】
1/根据断点列表获取解码的 开始与结束结点

Algorithm 3. Backwalk algorithm with breakpoints
Input: CFG f, List<BreakPoint> points
/* the last breakpoint is the node and probe value at the exit */
Output: the corresponding path
 ArrayList<Node> t = new ArrayList<Node>();		//initialization
 t.append(f.entry);					//t only contains the entry node here
 Node begin, end;
 foreach breakpoint bp in points do
 	//deal with a series of breakpoints
 	if bp.hasPrePoint() then
 		//the node of the pre-breakpoint is the boundary of backwalk
 		begin = bp.getPrePoint().getNode();
 	else:
 		begin = f.entry; 	
 	end = bp.getNode();
 	t.append(backwalk(bp.probe, f, begin, end));	//use Algorithm 2, and connect the path fragments
 return t;
[+]不大规范的DFD图:

APK  -->(反编译)  smali  -->(分块解析)  CFG graph<node, link > --> (instrument encode Al.1)  probe Smali  -->(重打包)  APK_Instrument  -->(log, decode, Al.2 Al.3)  --> Func_event

[+]数据结构:

1.Smali 项目,反编译后apk;

2.CFG (类名_方法名) : 图的记录文件 --》  NODE : 内容,出度数, 入度数;   Link:beg,end,注释,插桩offset, traceIsgo, 余数

3. 注入后的Smali 项目,重打包成APK_instrument;

4.获取运行后的log;

5. 根据log得出的Func_event, 事件流函数列表。

[+]了解C#的线程池

在ThreadPool中连续添加任务,在线程执行完毕后设置提醒,就可以继续执行下去;  全部自动管理,选择合理的资源利用。

【相关资料】

[+]在win8.1 中添加mindfusion

1.正确完整的win8.1系统, 使用特定的mindfusion包,可以不用安装.net framework。 【下载mindfusion

2.安装完成要使用的时候, 在project里面添加引用,浏览安装的mindfusion位置,添加进去就好。

【——1-5: 重写了部分代码,更新了数据结构】

[+]CFG图记录部分的数据结构要更改:

CFG (类名_方法名) : 图的记录文件 --》  NODE : 内容,出度数, 入度数,插桩offset;   Link:beg,end,注释, traceIsgo, 余数

虽然插桩的位置是根据边来确定的,但是插桩之前就要对偏移进行判断;

目前算法与之前不同,每个节点的开始和结尾都有可能插桩。

【1-17: 发现了一些bug,打算明天开始解决。都是小问题】

[+]CFG数据结构继续更新:

NODE : 内容,出度数, 入度数,插桩offset,结点上方是否插桩,结点下方是否插桩;(出于避免同一个结点重复插桩的情况)

[+]try-catch类型的控制结构中, ‘.locals num’域的变量存在问题:

locals 不能超过13个,14以上就会出错。

实例的测试代码中,

【方案】注释部分如果增加,可以强行使得.locals 变量数据增大,可以绕开这个问题。

trycatchTestCode:

private void tryCatch(int drumsticks, String peple) {
/*
	String ss = "ssss";
	     String ss1 = "ssss";
	     String ss2 = "ssss";
	     String ss3 = "ssss";
	     String ss4 = "ssss";
	     
	     String ss5 = "ssss";
	     String ss6 = "ssss";
	     String ss7 = "ssss";
	     String ss8 = "ssss";
*/
		 try 
	        {
	            int i = Integer.parseInt(peple);
	            try 
	            {
	                int m = drumsticks / i;
	                int n = drumsticks - m * i;
	                String str = "这是其他的字符串四十看";
	                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
	            } 
	            catch (ArithmeticException e) 
	            {
	                Toast.makeText(MainActivity.this, "这是其他的事实字符串四十看!!", Toast.LENGTH_SHORT).show();
	            }
	        } 
	        catch (NumberFormatException e) 
	        {
	            Toast.makeText(MainActivity.this, "这是其他的事实字符串四十看!", Toast.LENGTH_SHORT).show();
	        }
	        
	 }
目前就是先强行改动到这种情况。
[+]invoke- 函数时候,传入参数的变量数值有限。最大可以调用 v15的寄存器,超过了,就出现语法错误。

方案】根据压栈,弹栈的原理,存储,使用寄存器。

问题repo】 当locals 变量数小于4个情况下,可能会覆盖 r 的值。

问题repo——方案】变量数的判断,小于4的情况下,另外处理。

[+]一个结点可能会被多次注入

方案】每个节点增加注入判断

问题repo】某些还是会多次注入:    ‘:cond_0’

***********耽误了一段时间,但总算自己比较满意的结束了第二阶段了******************

--1-18

【改变余数注入的规则: jmp 的。】 在跳出去之前 ,先 remainder ,再log, 再jmp。

--1-19

【packed-switch】
[9]: :pswitch_data_0
.packed-switch 0x0
    :pswitch_0
    :pswitch_1
    :pswitch_2
    :pswitch_3
.end packed-switch
这个模块的代码不能拆开。
【方案:】因为这段代码上面的代码块一般为nop,因此对nop快不作处理,让其不连接这个代码块。
选择性的代码直接连接到这里,不用进行注入了。


【重打包成功之后,不能运行,出现verrify 的错误】
01-19 03:39:41.493: E/AndroidRuntime(404): java.lang.VerifyError: com.example.testifelse.MainActivity


猜测很可能是我的 注入语句出了问题,很可能是move 语句
【12:06】锁定就是move语句用的不正确。
【解决:在move 移动值之前,寄存器没有初始化】
—— 删除方法刚开始的move语句。
—— 初始化的时候,把所有新增的寄存器和 v0,v1,v2,v3初始化。确保使用的每个寄存器都是初始化过的。
      【依旧出错??问题在哪里?】—— 寄存器的类型在使用过程中会变化,不是同一个类型的,move出错。
                                      同一类型的,或者目标寄存器没有初始化类型的,才能move。
      【如何确保,在不改变原寄存器v0-v3 值得情况下,使用它们?】
        【拟方案:】因为px寄存器可以作为vx寄存器的替代,且是从后往前替代。那么可以考虑在原参数px的基础上累加使用。
                     那么对于传入参数少于11个的方法都是有效的,传入参数超过11个? 太恐怖了====
                   tmp-p0,  sb-p1,  r-p2,  sz-p3
        【!!!x拟方案】错误: 没有传入参数,使用px类寄存器是不合法的。
      【使用range 调用方法】-- 
                传入的是两个参数,就要使用不同的寄存器。 传入一个参数就是一种寄存器。【貌似可行!!!!1-20 20:27】
       【解决的思路:】参考apktool是如何解决高位寄存器函数调用问题的,构造极端情况的函数调用。
    smali 语法:http://my.oschina.net/xiahuawuyu/blog/57146


【1-20: backedge 边除了case, jmp; 还有dowhile循环的if-,没有解决???】

【如果目标结点是exitNode,即使是一条入度的边,也要继续注入】--ok
【1-20:   注入的log输出问题,%90解决了,trycatch 还有一点问题。 v27->v4,  不存在的寄存器? 发生错误?】--ok
         【1-21:trycatch, 在:try_end_0  前后的位置貌似不能插入代码?? 奇怪】


【1-22 .catch 的问题再次折磨】

     观察.catch的格式特点,发现注入应当在.line之后,.line之中插入,会出错。        
    .line 95 (这之后注入是可以的)   
    .local v10, s5ss:Ljava/lang/String;
    invoke-static/range {p2 .. p2}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I


    :try_end_0
    .catch Ljava/lang/NumberFormatException; {:try_start_0 .. :try_end_0} :catch_1
【--如果是连续的两个.catch, 直接在当前.catch的前面注入
    :try_end_1
    .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :catch_0
(这里注入)
    .catch Ljava/lang/NumberFormatException; {:try_start_1 .. :try_end_1} :catch_1
   

【1-26. .catch move的注入部分问题解决】--ok

[+]两个地方,在程序刚开始, .prologue 的地方,要加入 tmp变量的初始化;将tmp的值放入r中的move语句要在move-exception 语句之后,因为:catch_1 与后面的move-exception语句应该连在一起的。
[++]总结起来,.catch 语句注入应该注入的问题有:
    a. .catch 语句注入的思路。 在进入.catch 语句之前,无论是否执行了catch,都计算r,但是将算到的值放入tmp中,再在目标 :catch_0位置,将tmp值放入r中。
    b. .catch段注入注意问题:
    [b1]观察.catch的格式特点,发现注入应当在.line之后,.line之中插入,会出错。        
    .line 95 (这之后注入是可以的)   
    .local v10, s5ss:Ljava/lang/String;
    invoke-static/range {p2 .. p2}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
    :try_end_0
    .catch Ljava/lang/NumberFormatException; {:try_start_0 .. :try_end_0} :catch_1
    [b2]--如果是连续的两个.catch, 直接在当前.catch的前面注入
    :try_end_1
    .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :catch_0
    (这里注入)
    .catch Ljava/lang/NumberFormatException; {:try_start_1 .. :try_end_1} :catch_1
    c. :catch_1 段注入问题:
    [c1]应当在程序初始化的时候 ,.prologue 部分,将tmp变量初始化为0,确保为int型。
    [c2]注入的部分应当在move-exception 之后。
     :catch_1
     move-exception v3
     (这里注入)


[+]dowhile 的问题,没有找到合适的办法,在backedge部分输出log,直接忽略backedge边,到最终才输出结果。
    [++]!!需注意的问题,在循环层数,或者控制流特别多的情况下,可能出现r的值溢出!【caution!】



【1-28. 可能输出的log里面,不需要断点】--错误

【1-29. 在一个方法中,并不都是 连续的调用方法】

     beg 3 3 beg 4 4 end 2 3 beg 1 1 end 3 3 end 这种也有可能的
     【解决:利用递归的方法,最终解决】

【1-30. 还是需要断点,否则形如r=0 的log值,将无法获得正确的路径值,必须根据断点划分子图,

      break( 3 , 8 , 9)】--ok , now 主要程序已经由上到下打通,
现在就是调试 + 完善分析所有文件 + 加上多线程 + 图形化显示。

【1-31. log能够成功解析目前的sample程序。 暂时告一段路】

[+]今日任务:
   [++]1.解析apk的完善 ---ok
   [++]2.图形化显示cfg的完善 -- ok 2-3 --[smali单个分析显示的问题]--ok
   [++]3.列表化cfg-method -- ok 2-3
   [++]4.图形化解析的log-cfg(标记出走过的路径),及对应的列表--ok
   [++]5.多线程执行分析程序 --ok
   后期任务:
   [++]1.列表的cfg和log-cfg,用tabcontrol分别放置--ok
   [++]2.加上进度条  -- ok 2-15
   [++]3.其他的适当美化
   [++]4.测试系统
   [++]5.菜单栏以及工具栏显示
   [++]6.把事件的函数log, 显示成调用的形式

【2.2 treeview cfg-method 】

     终于找到一个还算靠谱的。http://blog.csdn.net/lianchangshuai/article/details/7741698--可以成功treeview
     如果可以成功,一定好好谢谢这个作者。
     真的可以成功,只是在效率上稍微有点低。不知该如何改进的。--
   【考虑对于两个文件的问题处理】--
    【遍历的应该是分析之后的文件,而不是smali文件】

【2.3 】

    [+]分析单个smali文件的时候,所有的节点都标记为0 个outedge--都成红色?问题 -- 没有执行计算入读。 解决。
    [+]log-event 树形结构的问题 -- 打出的method-log 中,应当包含完整的包路径-- 解决。

【2.5 】

   问题:[+]出现零个代码块的情况--接口,解决。
         [+]没有处理文件名称过长的问题。 

【2.6 多线程执行时,溢出的错误?】

    http://blog.csdn.net/eastmount/article/details/19453107--treeview 显示加号

【2.10 举证优化阶段】---可能在答辩阶段,或者论文的测试阶段显示出来。

[+]两个木马的例子-- 1个大一点,一个小一点或者都小的,要不同类别,有按钮点击,有事件的。有分析过的。
[+]统计事件还原的成功率,准确率。(稍加杜撰把)
[+]统计插桩的代码量,以及插桩的代码对于源程序造成的overhead数据。

【2.11 论文主导阶段】

[+]CFG相关领域的论文, 安全,软件测试等。
[+]关于程序分块,与路径剖析。


【2-14 进度条与后台处理线程】

多线程同步http://blog.csdn.net/wangqiuyun/article/details/13509225


【++++++++++++++++++++++++++++++++++】项目感悟
1、软件的初始逻辑设计,或者功能设计,一定从人类可以直观理解的角度进行。

预先可以打一个逻辑草稿,这个草稿必须是人能够直观看懂的逻辑。以后的实现都尽可能的基于划定的草稿,进行具象化。这样的设计,便于后期维护与优化。


【++++++++++++++++++++++++++++++++++】

【++++++++++++++++++++++++++++++++++】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值