Friday, 20 September 2013

Xposed使用说明

Xposed原理简介

Xposed基于两个部分,底层是替换/system/bin/app_process,增加Hook替换函数的接口,主体框架为XposedBridge,由de.robv.android.xposed.XposedBridgemain方法入口。

开发一个基于Xposed的插件

这里以一个动态监测sendTextMessage的Demo为例介绍如何基于Xposed框架实现一个插件。

  1. AndroidManifest.xml

    Xposed会读取Application下的相关meta-data,例如这里:

     <meta-data android:value="true" android:name="xposedmodule"/>
     <meta-data android:value="2.1*" android:name="xposedminversion"/>
     <meta-data android:value="Test for Xposed." android:name="xposeddescription"/>
    
  2. IXposedHookLoadPackage IXposedHookLoadPackage接口的handleLoadPackage方法在Package Load前调用。

     public class Main implements IXposedHookLoadPackage {
         public void handleLoadPackage(final LoadPackageParam pkg) throws Throwable {
             XposedBridge.log("Loaded app: " + pkg.packageName);
    

    在测试程序运行后输出日志如下:

     09-17 17:25:11.319: I/Xposed(13475): Loaded app: com.example.smshook
    
  3. findAndHookMethod

    实现对指定类的指定方法进行Hook,并且通过override beforeHookedMethodafterHookedMethod来记录和改变原始行为。

         findAndHookMethod("android.telephony.SmsManager", pkg.classLoader, "sendTextMessage",
                 String.class,
                 String.class,
                 String.class,
                 PendingIntent.class,
                 PendingIntent.class,
         new XC_MethodHook() {
         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
             XposedBridge.log("before send");
             Object[] args = param.args;
             XposedBridge.log(args[0] + ": " + args[2]);
         }
    
         protected void afterHookedMethod(MethodHookParam param) throws Throwable {
             XposedBridge.log("after send");
         }
     });
    

    在测试程序点击发送短信后输出日志如下:

     09-17 17:25:12.150: I/Xposed(13475): before send
     09-17 17:25:12.150: I/Xposed(13475): 10086: test hello world.
     09-17 17:25:12.160: I/Xposed(13475): after send
    

参考

Cydia Substrate使用说明

Cydia Substrate是一个基于Hook的代码修改框架,其可以在Android、iOS平台使用,并实现修改系统默认代码。这里关注的是其在Android下的使用方式和基本原理。

使用说明

Substrate SDK实现了对Native API和Java API的Hook技术。

使用条件:

  1. 手机需要提权
  2. 需要安装Substrate
  3. 开发环境需要下载SDK

Java API Hook实例

  1. 修改AndroidManifest.xml

    • 添加权限

        <uses-permission android:name="cydia.permission.SUBSTRATE"/>
      
    • 在Application中需要添加meta-data,这里value可以替换成自己的实现类

        <meta-data android:name="com.saurik.substrate.main"
        android:value=".Main"/>
      
  2. 实现类必须有一个静态的 initialize方法,没有参数,返回为空

  3. 编译时需要将substrate-api.jar放入project/libs

相关源码:

MS.hookClassLoad("android.telephony.SmsManager",
    new MS.ClassLoadHook() {
       public void classLoaded(Class<?> arg0) {

          Method sendTextMessage;
          try {
             sendTextMessage = arg0.getMethod("sendTextMessage",
                new Class[] {
                 String.class,
                 String.class,
                 String.class,
                 PendingIntent.class,
                 PendingIntent.class
             });
          } catch (NoSuchMethodException e) {
              sendTextMessage = null;
          }

          if (sendTextMessage != null) {
             final MS.MethodPointer old = new MS.MethodPointer();
             MS.hookMethod(arg0, sendTextMessage,
                   new MS.MethodHook() {
                      public Object invoked(Object arg0,
                        Object... args)
                        throws Throwable {
                          Log.d("SMSHOOK", "pid = " + android.os.Process.myPid() + 
                                  "uid = " + android.os.Process.myUid());
                          Log.d("SMSHOOK", args[0] + ":" + args[2]);
                          return old.invoke(arg0, args);

                            }                   
                   }, old);
          }
       }
    });

运行结果:

09-20 10:28:12.121: D/SMSHOOK(2095): before send.
09-20 10:28:12.141: D/SMSHOOK(2095): pid = 2095uid = 10000
09-20 10:28:12.141: D/SMSHOOK(2095): 10086:test hello world.

Native Hook 实例

  1. 相关Android.mk

     LOCAL_MODULE    := smshook.cy                                                      
     LOCAL_SRC_FILES := main.cpp                                                        
    
     LOCAL_LDLIBS := -L$(LOCAL_PATH)/../lib -lsubstrate-dvm  
    
    • lib后缀为.cy.so
    • 需要以CPP方式编译
    • 需要链接libsubstrate-dvm.so
  2. 相关AndroidManifest.xml

    • 添加权限

        <uses-permission android:name="cydia.permission.SUBSTRATE"/>
      
    • installLocation设置

        android:installLocation="internalOnly"
      
    • Application相关设置

        Application的android:hasCode="false"
      

相关源码:

MSConfig(MSFilterExecutable, "/system/bin/app_process")                         

static jint (*_Resources$getColor)(JNIEnv *jni, jobject _this, ...);            

static jint $Resources$getColor(JNIEnv *jni, jobject _this, jint rid) {         
        jint color = _Resources$getColor(jni, _this, rid);                      
            return color & ~0x0000ff00 | 0x00ff0000;                            
}                                                                               

static void OnResources(JNIEnv *jni, jclass resources, void *data) {            
    // ... code to modify the class when loaded                                 
    jmethodID method = jni->GetMethodID(resources, "getColor", "(I)I");         
    if (method != NULL)                                                         
        MSJavaHookMethod(jni, resources, method,                                
            &$Resources$getColor, &_Resources$getColor);                        
}                                                                               

// this is a macro that uses __attribute__((__constructor__))                   
MSInitialize {                                                                  
    // ... code to run when extension is loaded                                 
    MSJavaHookClassLoad(NULL, "android/content/res/Resources", &OnResources);   
}

Tuesday, 20 November 2012

Debian之OpenVPN配置

1. OpenVPN安装
  Debian安装OpenVPN server: apt-get install openvpn
  配置脚本默认安装在/usr/share/doc/openvpn/examples/easy-rsa/2.0下
  配置文件默认放在/etc/openvpn

  MaxOSX安装OpenVPN客户端: tunnelblick

2. Server配置
  ./build-ca
  ./build-key-server server
  ./build-key client
  ./build-dh

  Server需要ca.crt, server.key, server.crt, dh1024.pem

  Server配置文件默认在/usr/share/doc/openvpn/examples/sample-config-files/server.conf
  
port 1194
proto udp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 202.107.105.13"
push "dhcp-option DNS 202.108.107.21"
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
启动OpenVPN server: /etc/init.d/openvpn start

配置IP转发: echo 1 > /proc/sys/net/ipv4/ip_forward
修改/etc/sysctl.conf: 取消注释net.ipv4.ip_forward = 1

配置iptables规则:
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
iptables -t nat -L查看规则配置是否成功

3. Client配置

client
dev tun
proto udp
remote 66.32.272.181 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
mute-replay-warnings
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client_kevin.crt
key /etc/openvpn/client_kevin.key
ns-cert-type server
comp-lzo
verb 3
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

Thursday, 28 June 2012

Virtual Attributes In Ruby

class Song 
  def initialize(name, artist, duration)
    @name = name 
    @artist = artist 
    @duration = duration 
  end 


  def to_s 
    "song: #{@name} -- #{@artist} (#{@duration})" 
  end 


  def durationInMinutes 
    @duration / 60.0 
  end 


  def durationInMinutes=(value)
    @duration = (value * 60).to_i 
  end 
end 


song = Song.new "aaa", "bbb", 240 
p song.instance_variables >> [:@name, :@artist, :@duration] 
p song.to_s               >> "song: aaa -- bbb (240)" 
song.durationInMinutes = 10 
p song.instance_variables >> [:@name, :@artist, :@duration] 
p song.to_s               >> "song: aaa -- bbb (600)"

Ruby之$_小记

  $_记录最后一行从gets或者readline的字符串。如果print不带参数则输出$_;如果if/while判断为一个正则表达式,则为正则表达式是否匹配$_。
gets        >> "aaa"
puts $_     >> "aaa"
print       >> "aaa"
if /a+/
  puts "bbb"
end         >> "bbb"
  ARGF是一个流,用作在脚本中处理文件,从命令行参数或者STDIN输入,ARGF会对ARGV的每一个参数当作文件流依次载入,并将其从ARGV中移除;如果ARGV为空,则从STDIN输入。
ARGF.each { |line| puts line if line =~ /Ruby/ }

Wednesday, 27 June 2012

MiniMagick/RTesseract安装小记

  1. gem install mini_magick
  2. apt-get install libmagick9-dev
  3. gem install rtesseract

Tuesday, 5 June 2012

[译]Password Cracking with GPUs

  原文见:      比较流行的几种HASH算法:   
  • MD5
  • SHA1/SHA256/SHA512
  • phpass:PHP-based site like WordPress
  Linux下将密码的HASH保存在/etc/shadow中,格式为
$id$salt$encrypted
其中id位代表HASH算法:
  • 1 = MD5
  • 5 = SHA-256
  • 6 = SHA-512
  使用GPU比使用CPU破解密码或者用作Bitcoin挖矿要快得多。简单的来说,GPU中有很多专用芯片做32位操作速度非常快,即使CPU可以做很多通用计算,GPU中的芯片做某些特殊类型的运算会更快,并且以一种更加并行的方式,详细的原因可以参考此文:Why a GPU mines faster than a CPU
  Why a GPU mines faster than a CPU中一文是如此解释的:GPU主要是辅助渲染3D图像和视觉效果。通常的计算机会配置更慢但是功耗更小和更便宜的IGPs(Integrated Graphics Processor集成图像处理器),其集成在主板上,而AGP/PCIe显卡能提供更强的图像处理。简单来说一个CPU核心每个时钟周期可以执行4条32位指令如果使用128位SSE指令集,如果使用256位AVX可以执行8条;然而对于GPU(Radeon HD 5970)每个时钟周期可以执行3200条32位指令使用其3200个ALUs和shaders(着色器)。
  CPU被设计为主要执行和决策,每个CPU中也有多个ALU,并且CPU中有大量的结构用来确保迅速的状态切换。另外:
  • 执行特权级别,用户态和操作系统的界限
  • 为程序创建虚拟内存
  • 向前兼容遗留代码
  GPU被设计为做图像处理,图像处理是很多重复性的工作,所以GPU中有大量的ALU,比CPU具有更强的数学计算能力。GPU更适合处理重复的运算而不是处理条件逻辑
  GPU上的ALU分成组,每个组公共管理,所以每个组内的ALU不能单独处理任务,对于Bitcoin挖矿来说就是重复尝试不同的HASH。对ATI Radeon 5970显卡来说,其有3200个流处理器,并且5970使用了VLIW-5体系结构,实际3200个流处理器只需要640个核心,每个核心每个时钟周期执行5条指令。Nvidia类似的称作"Cuda Cores",但是Nvidia没有采用VLIW结构,每个核心无法处理多条指令,所以单从核心数比较性能是不准确的,在计算SHA-256下,Nvidia比ATI差。对于ATI显卡通常有大量简单的ALU/shader(VLIW设计),并且通常运行在一个较低的时钟频率(1120-3200 ALUs at 625-900 MHz)。Nvidia采用微架构(microarchitecture),其包含少数更复杂的ALU和更高的时钟频率来补偿(448-1024 ALUs at 1150-1544 MHz):
  • AMD Radeon HD 6990: 3072 ALUs x 830 MHz = 2550 billion 32-bit instruction per second
  • Nvidia GTX 590: 1024 ALUs x 1214 MHz = 1243 billion 32-bit instruction per second
  所以对于基于ALU运算的操作,效果差异非常明显,如Bitcoin和暴力破解密码。对于Bitcoin来说基于SHA-256算法,有大量的32位循环右移操作,在AMD的GPU(BIT_ALIGN_INT)上只需要一个指令,在NvidiaGPU上需要三条指令(2 shifts + 1 add),在Bitcoin挖矿中,AMD GPU可以达到3x-5x更快的速度。详细可以参考当下各种CPU/GPU速度比较Mining hardware comparison
  利用GPU做密码破解除了安装显卡的相关驱动外,还需要AMD APP SDK for OpenCL库或者Nvidia CUDA库。破解工具选择Hashcat,Hashcat包含以下工具:
  • hashcat:基于CPU,支持最多的HASH算法
  • oclHashcat:基于GPU,支持部分HASH算法,内置字典攻击,穷举攻击,掩码攻击
  • oclHashcat-plus:优化的多HASH字典攻击,支持管道输入
  • oclHashcat-lite:优化攻击单个HASH,最快但支持算法最少
  • maskprocessor:生成字典,并管道输出给oclHashcat-plus
  如果是Nvidia GPU使用cuda开头的,否则使用ocl。
type example.dict | cudaHashcat-plus64.exe -m 400 example400.hash
  • 字典攻击:
  • cudaHashcat-plus64.exe -m 400 example400.hash example.dict
  • 计算破解速度:

  •   通过Speed看出每秒9973次比较,查看此网站可以估算破解时间Password Recovery Speeds。如果密码采用[a-zA-Z0-9]一共62个字符,如果是6位密码,有超过568亿种组合,除以每秒比较次数可以得到估计时间。
  • 穷举攻击
  •   maskprocessor用以下符号代表字符集:
    • ?d = all decimals (0–9)
    • ?l = lowercase characters (a–z)
    • ?u = uppercase characters (A–Z)
    • ?s = symbols
      并且可以自定义字符集-1(-2或者-3),然后使用?1(?2或者?3)来使用定义的字符集,例如生成一个6位密码:
    mp64.exe -1 ?d?l?u ?1?1?1?1?1?1