Ida Pro dbg String Commentor 插件

最近因为研究内容的关系,需要经常分析加固和混淆过的elf文件.真是比较耗费精力的事情啊.特别是ida pro与od不一样的, 寄存器窗口不会直接把字符串显示出来.所以,经常需要双击地址,再双击地址一直到一个字符串. 才知道当前在处理什么文件,或者处理什么内容.

函数更是这样了,初步调试很多函数看到入参和出参就能猜到函数功能了. 双击再双击是在麻烦, 如果能在每个调用函数的时候能直接看到入参和出参就好了.

我们对于一些常见的Hash函数(SHA1,MD5等),加解密函数(AES等), 通常是通过一些常量和一些固定的汇编逻辑来识别的. 如果能比较快速的识别出来哪些代码在运行的是Hash函数/加解密函数的逻辑,也能节省很多调试时间.

于是做了这么一个程序. 包含三个功能点:

  1. 识别字符串,以及字符串的指针(或者多层指针最终指向一个字符串),并且把字符串内容以comment的形式附加到指令处.

效果图:str  2.  记录函数入参与出参,并且以comment的形式附加到函数的调用处.

效果图:

func3. 识别各种常见的Hash函数以及加解密函数(的常量),并且以comment形式附加到识别出来的指令处.

效果图:

hash

项目地址:

https://github.com/thelongestusernameofall/dbgStrCmtor

应用资源文件格式解析及阿里破解示例

  1. 这篇文章对apk的资源文件的格式进行了详细的分析。可以作为日后文件分析时的参考资料
  2. 这篇文章中所述的通过修改aapt来达到自动生成加固版本apk的方式,是一个值得借鉴学习的好思路

 

原文链接:

http://bbs.pediy.com/showthread.php?t=207816

原文内容:
春节正好有点时间写文章和大家分享下。

目前大部份公司如阿里,腾讯,360等对apk资源保护的方法是通过自动化测试工具寻找一些异常的数据格式,安卓虚拟机及aapt对于这些异常的格式可以正常处理,而apktool工具处理分析时会出现异常。

找到这些异常的数据格式后,利用改装后的aapt工具,对apk打包时设置这些异常的格式,从而达到保护的作用。

本文主要介绍应用资源文件的格式,分析阿里的APK资源保护机制,给出了破解方法。

文章见附件的应用资源文件格式解析及阿里破解示例.doc 

模板和实例见 ARSCTemplate和helloworld.apk

doc描述附件

应用资源文件格式解析及阿里破解示例

Java中如何修改Jar中的内容[转载]

1.这篇文章讲了一种曲折的方式来修改jar中的字节码. 比较有趣,可以用来参考.原文链接:http://blog.csdn.net/jiangwei0910410003/article/details/45600385

如果原文链接可达推荐跳往原文链接阅读,有更好的界面布局.

2. 对于直接修改字节码,可以看我之前发表的文章: http://ieroot.com/2014/02/11/1435.html

############### Java中如何修改Jar中的内容 [转载]############

一、摘要

好长时间没写blog了,之前换了一家公司。表示工作更有战斗力了,可惜就是没时间写文章了。在这段时间其实是遇到很多问题的,只是都是记录下来,并没有花时间去研究解决。但是这周遇到这个问题没办法让我继续前进了。必须记录一下。以被后人使用。不多说了,进入主题。

二、前提

1、对于GA的了解(自行google)

2、对CampaignTrackingReceiver类的了解,他是当从GP上下载并且安装完成一个app的时候,发送一个广播,会在Intent中携带一些数据,一般是Refer值,这里可以区分从哪里下载的,具体简单的例子:A应用是我需要发布到GP上的应用,但是我们可能会在各个渠道上推广A,所以我们可能需要加上渠道号进行统计,所以这时候需要在A应用添加CampaignTrackingReceiver广播接收器,然后处理接收到的广播中的Intent的内容,解析出具体的渠道号,进行上报即可。所以说GP发送这个广播还是很奇特的,他发送了这个广播,然后等我们安装A并且运行了之后就可以接收到这个广播,等于这个广播发出去了,他会等待有一个接收器接受他。

3、本文中需要用到的工具下载地址:http://download.csdn.net/detail/jiangwei0910410003/8679153,下载完之后,首先要看一下txt文档中的说明。

三、问题描述

工程中接入了GA统计(Google提供的一种app统计功能的SDK),但是我们自己可能需要统计app从GP上下载的统计(这里一般是注册一个CampaignTrackingReceiver的广播),但是有问题就是GA的SDK中已经包含了CampaignTrackingReceiver类了,当时在弄的时候进入到了一个误区:就是认为如果app中想接收到这个广播的话。广播接收器的包名必须是:com.google.analytics.tracking.android,类名:CampaignTrackingReceiver,类似于下面的注册代码:

[html] view plaincopy

  1. <receiver  
  2.     android:name=“com.google.analytics.tracking.android.CampaignTrackingReceiver”  
  3.     android:exported=“true”>  
  4.     <intent-filter>  
  5.         <action android:name=“com.android.vending.INSTALL_REFERRER” />  
  6.     </intent-filter>  
  7. </receiver>  

但是之后发现不需要这样的,只要包名一样即可,其实从Android中发送广播的机制就可以知道。类名没有关系的,但是当时这个东西没办法测试的(需要发布一个测试app到GP上,时间上也是不允许的,只能听前辈的)。最后也是自己发布了一个测试app测试了才知道,不需要类名一样的,这个也算是一种收获,那么既然类名不一样的话,这里就没有问题了。就不会和GA中的类重复了。但是我在没有解释这个误区前用了另外的一种方法解决了这个问题。既然GA中有这个广播接收类,我们不能定义的话,可以在它的SDK中的这个广播类中插入一段代码:发送一个广播,把Intent中的数据带出来即可。思路有了,下面来看一下具体操作:

四、技术介绍

下面讲述的内容是基于上面的误区没有被解释的情况下说的,而且侧重点也不是解释误区。而是如何修改Jar中内容

首先说一下这个过程中的三个角色:jar,dex,smali

四个工具:dx.bat,dex2jar.bat,baksmali.jar,smali.jar

关系图如下:

我们这里需要修改jar中的代码,

首先说明一下,关于修改jar中的代码其实有很多方法的:

1、直接用压缩包工具打开jar中的class文件进行修改(除非你对指令集很熟悉,反正我是不愿意尝试)

2、使用jd-gui工具直接打开jar,进行修改(这个虽然能看懂代码,但是有一个问题就是如果代码被混淆了,那个难度还不如第一种方法了,所以也没有尝试)

好吧,那么第三种方法就是修改smali文件,这个文件的好处在于:指令简单,而且如果混淆了,也是没有关系的。关于smail的指令说明,可以自行google一下。很简单这里就不做解释了。

那么问题来了,如何将jar变成smali呢?这里没有发现他们两之间的直接转化工具,所以就曲线救国的方式做了。

首先将jar==>dex==>smali

然后修改smail中的内容

修改完之后会变成jar

smail==>dex==>jar

相当于dex是中转站了。

五、项目演示

技术实现说明完之后,下面来看一下Demo:

ReceiverLib工程

1、BtnReceiver.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.util.Log;  
  7.   
  8. public class BtnReceiver extends BroadcastReceiver{  
  9.   
  10.     private String action = “demo.action.myreceiver”;  
  11.       
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         Log.i(“demo”“action:”+intent.getAction());  
  15.     }  
  16.   
  17. }  

接收到广播然后打印log一下

2、MyReceiver.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.util.Log;  
  7.   
  8. public class MyReceiver extends BroadcastReceiver{  
  9.   
  10.     private String action = “demo.action.myreceiver”;  
  11.       
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         Log.i(“demo”“action:”+intent.getAction());  
  15.     }  
  16.   
  17. }  

3、Utils.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.Context;  
  4. import android.content.Intent;  
  5.   
  6. public class Utils {  
  7.       
  8.     public static void sendBroadcast(Context context,String action){  
  9.         Intent intent = new Intent();  
  10.         intent.setAction(action);  
  11.         context.sendBroadcast(intent);  
  12.     }  
  13.   
  14. }  

说明:BtnReceiver是点击Button之后发送的一个模拟广播,相当于上面需要改的CampaignTrackingReceiver类,MyReceiver是我们需要自己添加的广播接收器。

项目下载:http://download.csdn.net/detail/jiangwei0910410003/8679113

ReceiverDemo工程(需要导入ReceiverLib导出的jar)

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v7.app.ActionBarActivity;  
  5. import android.view.View;  
  6. import android.view.View.OnClickListener;  
  7.   
  8. public class MainActivity extends ActionBarActivity {  
  9.       
  10.     private String action = “demo.action.btnreceiver”;  
  11.   
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.activity_main);  
  16.         findViewById(R.id.btn).setOnClickListener(new OnClickListener(){  
  17.             @Override  
  18.             public void onClick(View v) {  
  19.                 Utils.sendBroadcast(MainActivity.this, action);  
  20.             }});  
  21.     }  
  22. }  

模拟发送一个广播

项目下载:http://download.csdn.net/detail/jiangwei0910410003/8679123

效果:

点击Button之后,发送了广播,BtnReceiver也接收到了。

那么下面就开始在BtnReceiver.java中插入代码,发送一个MyReceiver

首先使用dx命令,将我们上面ReceiverLib导出的jar变成dex文件:

dx命令的使用方式:dx –dex –output C:\receiver.dex receiver.jar

然后在将receiver.dex转化成smali:

baksmali.jar的使用方式:java -jar baksmali-2.0.5.jar -o c:\classout/ c:\receiver.dex 

我们可以查看smali文件,我们重点看BtnReceiver.smali文件,因为我们要在这里插入代码:

[java] view plaincopy

  1. .class public Lcom/example/receiverdemo/BtnReceiver;  
  2. .super Landroid/content/BroadcastReceiver;  
  3. .source “BtnReceiver.java”  
  4.   
  5.   
  6. # direct methods  
  7. .method public constructor <init>()V  
  8.     .registers 1  
  9.   
  10.     .prologue  
  11.     .line 8  
  12.     invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V  
  13.   
  14.     returnvoid  
  15. .end method  
  16.   
  17.   
  18. # virtual methods  
  19. .method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V  
  20.     .registers 7  
  21.     .param p1, “context”    # Landroid/content/Context;  
  22.     .param p2, “intent”    # Landroid/content/Intent;  
  23.   
  24.     .prologue  
  25.     .line 12  
  26.     invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;  
  27.   
  28.     move-result-object v0  
  29.   
  30.     .line 13  
  31.     .local v0, “action”:Ljava/lang/String;  
  32.     const-string v1, “demo”  
  33.   
  34.     new-instance v2, Ljava/lang/StringBuilder;  
  35.   
  36.     const-string v3, “action:”  
  37.   
  38.     invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V  
  39.   
  40.     invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;  
  41.   
  42.     move-result-object v2  
  43.   
  44.     invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;  
  45.   
  46.     move-result-object v2  
  47.   
  48.     invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I  
  49.   
  50.     const-string v4, “demo.action.myreceiver”  
  51.   
  52.     invoke-static {p1, v4}, Lcom/example/receiverdemo/Utils;->sendBroadcast(Landroid/content/Context;Ljava/lang/String;)V  
  53.   
  54.     const-string v5, “sendbroadcast”  
  55.   
  56.     invoke-static {v1, v5}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I  
  57.   
  58.     .line 14  
  59.     returnvoid  
  60. .end method  

关于smali指令网上自行搜索,很简单的,我们需要插入一行代码就是:

Utils.sendBroadcast方法:

这个过程中没有难度的,就不做解释了

下面我们就需要还原成jar了:

使用smali.jar工具将samli变成dex

用法:java -jar smali-2.0.5.jar c:\classout/ -o c:\receiver.dex

然后使用dex2jar命令将dex变成jar

用法:dex2jar receiver.dex

这时候我们就产生了修改之后的jar,我们将这个jar替换ReceiverDemo中的jar,然后运行结果:

成功显示了。我们的MyReceiver接收到了BtnReceiver中发送出来的广播了。

问题:

在这个过程中可能使用一些命令的时候会出现问题:

这个是class版本号不对,需要修改一下Eclipse中的Java编译器版本在编译导出jar就可以了。

其他的问题我这里没有遇到了。如果在开发的过程中遇到问题,记得回复留言,我尽量解答一下~~

六、总结

1、关于上面说到的问题,就是GA包中的类重复的问题,再次在说明一下,那个是个误区,我们自定一个Receiver也是可以的,不需要类名必须是:CampaignTrackingReceiver,所以有同学如果用到这个类的话,一定要记得,不要在入这个误区了。

2、关于修改jar中的内容,其实用途还是很多的,但是不是正规的解决方法,这个有点偏向于破解的方向了,这个是不符合开发原则的,这里说明一下就是为了多一条解决问题的办法,而且对逆向领域的一种知识补充,这个内容对逆向领域用处还是很大的。

3、关于这种方式使用与所有Java编写的程序,这里可能偏向于Android移动端了,但是如果JavaWeb中遇到这样的问题,也是可以使用这种方式解决的,不仅仅局限于Android方向。

Automating IDA Pro through IDAPython

1. Switch -O

-OIDAPython:$PATH_For_idapython_scripts $BinaryFileToProcess

idaq.exe -OIDAPython:E:\WorkSpace\PythonWorkSpace\idaPython\analyze.py hello

2. Switch -A

To make ida run in batch mode, not asking any questions (No human interactions need).

idaq.exe -A -OIDAPython:E:\WorkSpace\PythonWorkSpace\idaPython\analyze.py hello

 

Android DEX加壳技术草案

Android DEX加壳技术方案

一、什么是加壳?

加壳是在二进制的程序中植入一段代码,在运行的时候优先取得程序的控制权,做一些额外的工作。大多数病毒就是基于此原理。PC EXE文件加壳的过程如下:

 

 

二、加壳作用

加壳的程序可以有效阻止对程序的反汇编分析,以达到它不可告人的目的。这种技术也常用来保护软件版权,防止被软件破解。

 

三、Android Dex文件加壳原理

PC平台现在已存在大量的标准的加壳和解壳工具,但是Android作为新兴平台还未出现Dex加壳工具。Android Dex文件大量使用引用给加壳带来了一定的难度,但是从理论上讲,Android Dex加壳也是可行的。

在这个过程中,牵扯到三个角色:

1、加壳程序:加密源程序为解壳数据、组装解壳程序和解壳数据DEX文件

2、解壳程序:解密解壳数据,并运行时通过DexClassLoader动态加载

3、源程序:需要加壳处理的被保护代码

阅读该文章,需要您对DEX文件结构有所了解,您可以通过以下网址了解相关信息:

http://blog.csdn.net/jiazhijun/article/details/8664778

 

根据解壳程序和解壳数据在DEX文件中的不同分布,本文将提出两种Android Dex加壳的实现方案。

 

(一)解壳数据位于解壳程序文件尾部

 

该种方式简单实用,合并后的DEX文件结构如下。

 

 

加壳程序工作流程:

1、加密源程序DEX文件为解壳数据

2、把解壳数据写入解壳程序Dex文件末尾,并在文件尾部添加解壳数据的大小。

3、修改解壳程序DEX头中checksum、signature 和file_size头信息。

4、修改源程序AndroidMainfest.xml文件,修改程序入口Activity为解壳程序入口Activity。

 

解壳DEX程序工作流程:

1、读取DEX文件末尾数据获取借壳数据长度。

2、从DEX文件读取解壳数据,解密解壳数据。以文件形式保存解密数据到a.dex

3、通过DexClassLoader动态加载a.dex,并启动源程序入口Activity。

 

(二)解壳数据位于解壳程序文件头

 

该种方式相对比较复杂, 合并后DEX文件结构如下:

 

 

 

加壳程序工作流程:

1、加密源程序DEX文件为解壳数据

2、计算解壳数据长度,并添加该长度到解壳DEX文件头末尾,并继续解壳数据到文件头末尾。

(插入数据的位置为0x70处)

3、修改解壳程序DEX头中checksum、signature、file_size、header_size、string_ids_off、type_ids_off、proto_ids_off、field_ids_off、

method_ids_off、class_defs_off和data_off相关项。  分析map_off 数据,修改相关的数据偏移量。

4、修改源程序AndroidMainfest.xml文件,修改程序入口Activity为解壳程序入口Activity。

 

解壳DEX程序工作流程:

1、从0x70处读取解壳数据长度。

2、从DEX文件读取解壳数据,解密解壳数据。以文件形式保存解密数据到a.dex

3、通过DexClassLoader动态加载a.dex,并启动源程序入口Activity。

 

接下来的工作就是验证上面两种方案是否可行!

原文链接: http://www.myexception.cn/android/1246428.html

 

关于dex格式有些话要说

dex头:

[1] offset:0 – 7:

magic信息:

0x 00 35 33 30 0a 78 65 64

[2] offset: 8 – B

checksum:

计算方法: adler32算法计算dex除前12byte之外的其他dex内容(即除了magic以及checksum之外的dex内容的adler32算法).

———————————————————————–计算代码:

byte[] dexbytes = readFileAsBytes(dexpath);

Adler32 crcGenerator = new Adler32();
byte[] dex2 = new byte[dexbytes.length – 12];
for (int i = 0; i < dex2.length; i++) {
dex2[i] = dexbytes[i + 12];
}
crcGenerator.update(dex2);
long crc = crcGenerator.getValue();
String crcStr = Long.toString(crc, 16);

System.out.println(“crc:\t” + crcStr);

—————————————————————————

[3] offset: C – 1f

sha1 是自0x20开始至结尾的dex部分的sha1值. (dex除去magic,checksum,sha1自身部分的其他部分)

java代码:

----------------------------------------------------

byte[] dexbytes = readFileAsBytes(dexpath);

byte[] dex2 = new byte[dexbytes.length – 0x20];
for (int i = 0; i < dex2.length; i++) {
dex2[i] = dexbytes[i + 0x20];
}

MessageDigest sha1gen = MessageDigest.getInstance(“sha1”);
sha1gen.update(dex2);
byte[] sha1value = sha1gen.digest();
String sha1hex = “”;
for (byte b : sha1value) {
sha1hex += HEX_V[b>>4 & 0xf];
sha1hex += HEX_V[b & 0xf];
}
System.out.println(“sha1 signauture : \t” + sha1hex);

----------------------------------------------------

 

 

使用gdb和gdbserver调试Android C/C++程序

1,http://www.gnu.org/software/gdb/download/,下载最新版本的gdb源代码包,我使用的是gdb-7.6.tar.gz,使用tar命令进行解包(tar -xvzf gdb-7.6.tar.gz),cd进gdb-7.6/gdb目录,使用vi找到remote.c中的如下代码:
if(buf_len > 2 * rsa->sizeof_g_packet)

error(_(“Remote ‘g’ packet reply is too long: %s”),rs->buf);

将上面两行注释掉,添加如下代码

if(buf_len > 2 * rsa->sizeof_g_packet)
{
rsa->sizeof_g_packet = buf_len;
for(i = 0; i < gdbarch_num_regs(gdbarch); i++)
{
if(rsa->regs[i].pnum == -1)
continue;
if(rsa->regs[i].offset >= rsa->sizeof_g_packet)
rsa->regs[i].in_g_packet = 0;
else
rsa->regs[i].in_g_packet = 1;
}
}
使用如下命令对代码进行配置、编译和安装

./configure –target=arm-linux –prefix=/usr/local/arm-gdb -v

make

make install

2,gdbserver使用android4.2模拟器中自带的版本(v7.1)

3,将NDK编译好的C/C++可执行程序,上传到模拟器中/data/test目录下,假设可执行程序的名称为testHello。

4,使用命令:gdbserver :7000 /data/test/testHello 启动模拟器端的调试。

5,启动arm-linux-gdb之前,使用vi打开~/.bash_profile文件,在其中添加:

export PATH=$PATH:/usr/local/arm-gdb/bin,以便在程序的其他目录可以直接启动arm-linux-gdb程序

6,cd至ndk编译好的testHello文件所在目录

7,使用如下命令进行端口映射:adb forward tcp:7000 tcp:7000,将模拟器的7000端口和本机的7000端口进行映射

8,使用命令:arm-linux-gdb testHello启动gdb调试

9,使用target remote :7000 链接模拟器中gdbserver启动的服务。

10,自此,我们就可以使用gdb命令进行代码调试了。