Anroid开发安全技巧

混淆 加固 https 检测wifi代理 /**  * 检测是否使用了代理  * @return  */ public static boolean checkIsProxy(){     String host = System.getProperty("http.proxyHost");     String port = System.getProperty("http.proxyPort");     if (port == null) {         port = "-1";     }     int p = Integer.parseInt(port);     if(!TextUtils.isEmpty(host)&&p!=-1){         return  true;     }     return  false; } 检测是否手机是否root package com.bianyi.toufang.util; import android.content.Context; import android.content.pm.PackageManager; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; public class RootUtils {     public static boolean isDeviceRooted(Context context) {         return checkRootMethod1() || checkRootMethod2() || checkRootMethod3()||checkRootMethod4(context);     }     private static boolean checkRootMethod1() {         String buildTags = android.os.Build.TAGS;         return buildTags != null && buildTags.contains("test-keys");     }     private static boolean checkRootMethod2() {         String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",                 "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"};         for (String path : paths) {             if (new File(path).exists()) return true;         }         return false;     }     private static boolean checkRootMethod3() {         Process process = null;         try {             process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });             BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));             if (in.readLine() != null) return true;             return false;         } catch (Throwable t) {             return false;         } finally {             if (process != null) process.destroy();         } … Read more

Android 使用adb WIFI调试

嫌麻烦的话可以用Android Studio的插件Android wifi adb  ,这里记录了一下使用adb命令行进行wifi调试的过程,前提是手机 要和pc连同一个局域网 1. 手机连接usb 2. 命令行切到android sdk/platform-tools 目录下  E:>cd E:androiddevsdkplatform-tools 3.  查看设备    adb devices 4. 设置tcp端口  adb tcpip 5555 5. 连接设备  adb connect 192.168.3.172:5555 192.168.3.172是你手机设备在局域网的ip,下面就可以愉快的调试了 

Fiddler Android 7.0以上无法抓取https包问题解决

Fiddler提供的证书是.cer格式的证书,而安卓系统跟证书是.0格式的证书,我们需要做的是把fiddler证书先转换成安卓需要的.0证书格式,然后将证书拷贝到Andorid根证书存放目录 /system/etc/security/cacerts/目录下面,具体参见下面流程 第一步准备一部获取root权限的android手机 第二步浏览器输入fiddler证书下载地址,下载FiddlerRoot.cer证书 第三步,将cer证书转换成.0证书  openssl x509 -inform DER -subject_hash_old -in FiddlerRoot.cer    269953fb  #输出cer证书hash,转换成android证书的命名就用 269953fb.0 openssl x509 -inform DER -in FiddlerRoot.cer -text > 269953fb.0   #导出android证书 编辑输出的文件,把"—–BEGIN CERTIFICATE—–"到文件结束这部分移动到文件首部 第四步,将证书导入android系统证书目录  adb devices #查看设备 adb root #root用户   adb push 269953fb.0 /sdcard  #推送证书到手机  adb disable-verity  adb reboot  adb remount  adb root  adb shell  su  mount -o rw,remount /system  cp /sdcard/269953fb.0 /system/ect/security/cacerts/ cd /system/etc/security/cacerts chmod 644 269953fb.0  #分配权限  exit; 这样证书就被导入到android根目录了,打开任意app,小程序,fiddler完美展示数据,舒服 ~ 参考链接 http://wiki.cacert.org/FAQ/ImportRootCert#Android_Phones_.26_Tablets https://blog.csdn.net/xiangguiwang/article/details/76400805 https://segmentfault.com/a/1190000017035564 https://www.openssl.org/docs/manmaster/man1/x509.html https://blog.csdn.net/houxn22/article/details/81901520 ps:2020.4.8更新   参考链接  https://blog.csdn.net/liuluok123/article/details/95971731 三、Openssl安装完成后把证书导入到Linux系统下并进行转换 转换命令: 1.openssl x509 -inform der -in fiddler.cer -out fiddler.pem 2.openssl x509 -inform PEM -subject_hash_old -in fiddler.pem | head -1 得到类似字符串:9a5ba575 … Read more

Thinkcmf5 七牛云插件上传没有后缀不显示问题解决

最近发现用Thinkcmf开发的程序迁移服务器后,七牛云出了问题,cms后台上传的时候,看着七牛那边存储的文件不带后缀,切前台是带后缀的导致前台图片不显示问题。看了下七牛插件的源码,发现public/plugins/qiniu/Controller/AssetController里面的saveFile方法有些问题         $signingStr    = "/move/{$encodedEntryURISrc}/{$encodedEntryURIDest}";         $authorization = $auth->signRequest($signingStr, '');         $url = 'http://rs.qiniu.com/' . $signingStr;         $response = $client->post($url, null, ['Authorization' => 'QBox ' . $authorization]); 上面是改文件的一部分源码,执行上面程序七牛http返回码会直接301,原因是signingString多了第一个反斜线,去掉反斜线后,七牛返回的错误是bad_token,错误码是401,那就是token生成有误,token生成是   $authorization = $auth->signRequest($signingStr, ''); 具体代码逻辑可以自己点进去看下,我没有找到官网源码token生成的bug,所以这里我修复的方法是不走原来代码的逻辑,直接用bucketmanager替换原来的方式,整个saveFile方法如下:  public function saveFile()     {         $userId = cmf_get_current_admin_id();         $userId = $userId ? $userId : cmf_get_current_user_id();         if (empty($userId)) {             $this->error('error');         }         $validate = new Validate([             'filename' => 'require',             'file_key' => 'require',         ]);         $data = $this->request->param();         $result = $validate->check($data);         if ($result !== true) {             $this->error($validate);         }         $fileKey = $data['file_key'];         $suffix = cmf_get_file_extension($data['filename']);         $config = $this->getPlugin()->getConfig();         $accessKey = $config['accessKey'];         $secretKey = $config['secretKey'];         $auth = new Auth($accessKey, $secretKey);         $qiniuconfig=new Config();         $bk=new BucketManager($auth,$qiniuconfig);         $err=   $bk->rename($config['bucket'],$fileKey,$fileKey.".{$suffix}");         if($err){             $this->error($err);         }         list($fileinfo,$error)=$bk->stat($config['bucket'],$fileKey.".{$suffix}");         if($error){             $this->error($error);         }         $findAsset = Db::name('asset')->where('file_key', $fileKey)->find();         if (empty($findAsset)) {             Db::name('asset')->insert([                 'user_id'     => $userId,                 'file_size'   => $fileinfo['fsize'],                 'filename'    => $data['filename'],                 'create_time' => time(),                 'file_key'    => $fileKey,                 'file_path'   => $fileKey . ".{$suffix}",                 'suffix'      => $suffix             ]);         }         $this->success('success');     } 亲测没有问题

微信小程序解包过程记录

小程序包导出过程网上很多,不缀余,大体就是类似 adb pull /data/data/com.tencent.mm/MicroMsg/xxx/appbrand/pkg C:UsersAdamDesktop 这种过程,记录一下含有分包文件的小程序的解包过程。 1. 夜神模拟器导出小程序包2. 安装nodejs3. 下载 wxappupacker4. 安装依赖` npm install esprima   npm install css-tree   npm install cssbeautify   npm install vm2  npm install uglify-es  npm install js-beautify  npm install escodegen `   5.node wuWxapkg.js 主包名  6.node wuWxapkg.js 分包名  7.node wuWxss.js 分包文件夹/pages/groups,这里groups是分包下的名字,抽取wxss  8.node wuJs.js 分包文件夹/pages/groups/app-service.js  抽取js  9. node wuWxml.js 分包文件夹/pages/groups/page-frame.js 抽取wxml  10. 手动合并主包分包文件

XiunoBBS 七牛上传插件

   这几天抽着闲暇时间搞了一个bbs,刚开始本来想用discuz,无奈界面太丑,漏洞也多,之前在gitee上发现过一个不错对的开源轻论坛框架xiunobbs,就拿它来搞了。二次开发过程中有一个需求,我想把附件传到七牛,不保存在服务器上,这样能节省服务器带宽,xiuno插件市场提供了一个免费插件,但是可能跟版本相关,已经不能用了,所以就自己弄了一个,今天就免费分享给大家。 安装方式是首先把插件adam_qiniu拖放到plugins文件夹下,然后登陆xiuno后台插件,本地插件,安装即可,在设置里面设置上七牛云的ak,sk,附件上传地址,bucket即可。 安装后上传的附件,不会再保存在upload目录下,上传到七牛后,会自动删除本地文件,这里有一个问题,附件下载的时候会寻找本地文件,没有的话会报attach_not_exist错误,然而本地附件已经被删除了,所以这里需要屏蔽到这块逻辑,在route/attach.php文件下大概131行,备注掉如下代码 : //!is_file($attachpath)AND message(-1, lang('attach_not_exists')); 在model/attach.func.php文件插入  // hook attach_assoc_post_middle.php 源码上下文这样: // 插入后,进行关联 $aid = attach_create($arr);          // hook attach_assoc_post_middle.php $post['message'] = str_replace($file['url'], $desturl, $post['message']); $post['message_fmt'] = str_replace($file['url'], $desturl, $post['message_fmt']); 本来想用hook方式解决这个问题,但是由于本人对框架还不是很熟悉,没有找到好的hook方式。 总结一下安装和配置步骤: 安装adam_qiniu 配置ak,sk,上传url,bucket 备注掉 route/attach.php 131行代码  model/attach.func.php 234行插入  // hook attach_assoc_post_middle.php  如果想恢复本地存储,卸载插件,然后取消上面备注掉的代码即可 下载地址: https://github.com/adamin1990/adam_qiniu https://gitee.com/adamin/adam_qiniu PS:关于安装插件后无法卸载问题,取消备注 view/js/bbs.js第124行   //window.location = jthis.attr('href');

通用点击按钮请求API复制JS代码

    $(function () {         function Base64() {             // private property             _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";             // public method for encoding             this.encode = function (input) {                 var output = "";                 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;                 var i = 0;                 input = _utf8_encode(input);                 while (i < input.length) {                     chr1 = input.charCodeAt(i++);                     chr2 = input.charCodeAt(i++);                     chr3 = input.charCodeAt(i++);                     enc1 = chr1 >> 2;                     enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);                     enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);                     enc4 = chr3 & 63;                     if (isNaN(chr2)) {                         enc3 = enc4 = 64;                     } else if (isNaN(chr3)) {                         enc4 = 64;                     }                     output = output +                         _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +                         _keyStr.charAt(enc3) + _keyStr.charAt(enc4);                 }                 return output;             }             // public method for decoding             this.decode = function (input) {                 var output = "";                 var chr1, chr2, chr3;                 var enc1, enc2, enc3, enc4;                 var i = 0;                 input = input.replace(/[^A-Za-z0-9+/=]/g, "");                 while (i < input.length) {                     enc1 = _keyStr.indexOf(input.charAt(i++));                     enc2 = _keyStr.indexOf(input.charAt(i++));                     enc3 = _keyStr.indexOf(input.charAt(i++));                     enc4 = _keyStr.indexOf(input.charAt(i++));                     chr1 = (enc1 << 2) | (enc2 >> 4);                     chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);                     chr3 = ((enc3 & 3) << 6) | enc4;                     output = output + String.fromCharCode(chr1);                     if (enc3 != 64) {                         output = output + String.fromCharCode(chr2);                     }                     if (enc4 != 64) {                         output = output + String.fromCharCode(chr3);                     }                 }                 output = _utf8_decode(output);                 return output;             } … Read more

PDO实现mysql数据库数据库备份

$db_hostname="localhost"; $db_database="数据库名"; $db_username="root"; $db_password="xxx"; $DBH = new PDO("mysql:host=$db_hostname;dbname=$db_database; charset=utf8", $db_username, $db_password); //put table names you want backed up in this array. //leave empty to do all //要备份的表 //全备份置空 $tables = array(); backup_tables($DBH, $tables); function backup_tables($DBH, $tables) {     $DBH->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL ); //Script Variables     $compression = false;     $BACKUP_PATH = "/data/www/backup/";     $nowtimename = time(); //create/open files  创建开启文件     if ($compression) {         $zp = gzopen($BACKUP_PATH.$nowtimename.'.sql.gz', "a9");     } else {         $handle = fopen($BACKUP_PATH.$nowtimename.'.sql','a+');     } //array of all database field types which just take numbers     $numtypes=array('tinyint','smallint','mediumint','int','bigint','float','double','decimal','real'); //get all of the tables     if(empty($tables)) {         $pstm1 = $DBH->query('SHOW TABLES');         while ($row = $pstm1->fetch(PDO::FETCH_NUM)) {             $tables[] = $row[0];         }     } else {         $tables = is_array($tables) ? $tables : explode(',',$tables);     } //cycle through the table(s)     foreach($tables as $table) {         $result = $DBH->query("SELECT * FROM $table");         $num_fields = $result->columnCount();         $num_rows = $result->rowCount();         $return=""; //uncomment below if you want 'DROP TABLE IF EXISTS' displayed //$return.= 'DROP TABLE IF EXISTS `'.$table.'`;'; //table structure         $pstm2 = $DBH->query("SHOW CREATE TABLE $table");         $row2 = $pstm2->fetch(PDO::FETCH_NUM);         $ifnotexists = str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $row2[1]);         $return.= "nn".$ifnotexists.";nn";         if ($compression) {             gzwrite($zp, $return);         } else {             fwrite($handle,$return);         }         $return = ""; //insert values         if ($num_rows){ … Read more

PHP gzdeflate+str_to13+pack的一种加密解密代码方式

首先我们要加密的明文是: $test=<<<'EVE' echo '<script>alert("nihao")</script>';die; EVE; 字符串转16进制,16进制还原的方法 function String2Hex($string){     $hex='';     for ($i=0; $i < strlen($string); $i++){         $hex .= dechex(ord($string[$i]));     }     return $hex; } function Hex2String($hex){     $string='';     for ($i=0; $i < strlen($hex)-1; $i+=2){         $string .= chr(hexdec($hex[$i].$hex[$i+1]));     }     return $string; } 加密: $test1= gzdeflate($test);  #压缩 $test1=base64_encode($test1);  #base64编码 $adam=String2Hex(str_rot13($test1));  #选rot13转换 在转换成16进制 加密后的字符串: 463033426c537144676c794259666266585953596d527867586753446c66695a465a6b4b30654745756a64654a367178637962514e4e3d3d 解密: $ev=str_rot13(pack("H*",$adam));  #16进制还原,再rot13转换 $decoded=gzinflate(base64_decode($ev)); #base64解码,再gzinflate解压还原 这种方式可能用户部分代码混淆,留网站后门等。