qq聊天记录查看器手机器(查看msg聊天记录)

一般情况下,Android手机用户在拿到新机后,可能会做以下三件事。

一、水货用户立马重新刷机,然后对手机进行ROOT,国行用户思考再三后也ROOT掉手机(Android手机软件运行在普通用户权限,程序对系统本身没有控制权。而所谓“ROOT掉手机”就是通过一些手段让Android手机可拥有ROOT权限,之后软件通过“ROOT权限”可以随意修改、访问手机中所有资源)
qq聊天记录查看器手机器(查看msg聊天记录)

二、将手机ROM中自带的广告软件、无用软件精减掉来对手机进行优化

今天的测试在手机必须拥有ROOT权限下才能完成,这在现实大多数环境下是成立的。

程序分析

今天分析之前,先说说Dalvik反汇编代码的阅读。有朋友对我直接读Small文件的反编译代码这种方式有些不赞同,认为用JD-GUI工具来阅读DEX转的JAR包更方便,我个人认为,Dalvik 反汇编代码的阅读是必须要掌握的,因为DEX2JAR不是万能的,很多时候DEX2JAR就会失败无法生成JAR文件,使用JD-GUI读JAVA代码固然是好,但从基础上掌握反汇编的阅读也是很重要的。

.method protected onCreate(Landroid/os/Bundle;)V

.locals 4

.parameter

.prologue

.line 41

invoke-super {p0, p1},Lcom/tencent/mobileqq/app/BaseActivity;->onCreate(Landroid/os/Bundle;)V

#这里的父类也是TX自己编写的

.line 42

sput-object p0,Lcom/tencent/mobileqq/activity/SplashActivity;->instance:Lcom/tencent/mobileqq/activity/SplashActivity;

.line 43

invoke-virtual {p0},Lcom/tencent/mobileqq/activity/SplashActivity;->getIntent()Landroid/content/Intent;

.line 44

const/4 v0, 0x1

invoke-virtual {p0, v0},Lcom/tencent/mobileqq/activity/SplashActivity;->requestWindowFeature(I)Z

.line 45

invoke-virtual {p0},Lcom/tencent/mobileqq/activity/SplashActivity;->getWindow()Landroid/view/Window;

move-result-object v0

const/16 v1, 0x400

invoke-virtual {v0, v1},Landroid/view/Window;->addFlags(I)V

.line 46

const v0, 0x7f03007f

invoke-virtual {p0, v0},Lcom/tencent/mobileqq/activity/SplashActivity;->setContentView(I)V

#设置要显示View

.line 47

new-instance v0,Landroid/os/Handler;#??new一个Handler??

invoke-direct {v0},Landroid/os/Handler;-><init>()V

iput-object v0, p0,Lcom/tencent/mobileqq/activity/SplashActivity;->a:Landroid/os/Handler;#保存Handler

.line 52

iget-object v0, p0,Lcom/tencent/mobileqq/activity/SplashActivity;->a:Landroid/os/Handler;

iget-object v1, p0,Lcom/tencent/mobileqq/activity/SplashActivity;->a:Ljava/lang/Runnable;

const-wide/16 v2, 0x7d0 #延迟的时间间隔

invoke-virtual {v0, v1,v2, v3}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z

#??延迟启动一个线程进行登陆操作??

.line 54

invoke-virtual {p0},Lcom/tencent/mobileqq/activity/SplashActivity;->getApplication()Landroid/app/Application;#获取Application

move-result-object p0

.line 55

.line 56

move-result-object v0#调用a()方法并比较结果,用户是否获取成功

if-eqz v0, :cond_0

move-result-object v0

invoke-virtual {v0},Lcom/tencent/qphone/base/remote/SimpleAccount;->getSid()Ljava/lang/String;

move-result-object v0#getSid()获取SID自动登陆字符串

if-eqz v0, :cond_0

.line 58

move-result-object v0

invoke-virtual {v0},Lcom/tencent/qphone/base/remote/SimpleAccount;->getUin()Ljava/lang/String;

move-result-object v0

invoke-static {v0},Lcom/tencent/mobileqq/log/ReportLog;->setUserUin(Ljava/lang/String;)V

.line 59

move-result-object v0

invoke-virtual {v0},Lcom/tencent/qphone/base/remote/SimpleAccount;->getSid()Ljava/lang/String;

move-result-object v0

invoke-virtual {v0},Ljava/lang/String;->getBytes()[B

move-result-object v0

invoke-static {v0},Lcom/tencent/mobileqq/log/ReportLog;->setSig([B)V

#ReportLog记录结果,到这里用户就可以算是自动登陆了

.line 65

:cond_0

invoke-static {},Lcom/tencent/qphone/base/util/LoginHelper;->getCommonConfig()Ljava/lang/String;

move-result-object v0 #听名字是获取通用配置,跟踪发现是JNI调用获取信息,这里可以不跟

.line 66

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

move-result v1

.line 67

invoke-virtual {v0, v2},Ljava/lang/String;->indexOf(Ljava/lang/String;)I

move-result v2

.line 69

if-ltz v1, :cond_1

if-le v2, v1, :cond_1

.line 70

invoke-virtual {v3},Ljava/lang/String;->length()I

move-result v3

add-int/2addr v1, v3

invoke-virtual {v0, v1,v2}, Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-object v0

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

move-result-object v0

.line 71

sput-object v0,Lcom/tencent/mobileqq/log/ReportLog;->URL_LOG_UPLOAD:Ljava/lang/String;

.line 72

move-result-object v0

invoke-static {v0, p0},Lcom/tencent/mobileqq/log/ReportLog;->upload(Lcom/tencent/mobileqq/utils/httputils/HttpCommunicator;Landroid/content/Context;)V

.line 74

:cond_1

const/4 v0, 0x0

const-string v1,"SplashActivity onCreate()"

invoke-static {v0, v1},Lcom/tencent/mobileqq/log/ReportLog;->appendLog(Ljava/lang/String;Ljava/lang/String;)V

.line 81

return-void

.end method

在OnCreate()方法中,创建了一个Handler对象,Handler中加入了一个新线程,其实Handler与主线程使用了同一线程,所以在这里主线程就转去执行它的Run()方法了,新线程的实现代码在“ly.smali”文件中,打开这个文件看Run()方法:

.method public final run()V

.locals 5

.prologue

const-wide/16 v3, 0x0

.line 107

sget-object v0,Lcom/tencent/mobileqq/activity/NotificationActivity;->instance:Lcom/tencent/mobileqq/activity/NotificationActivity;

iget-object v0, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity; #获取SplashActivity对象

move-result-object v0

if-nez v0, :cond_2

.line 108

iget-object v0, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

const/4 v2, 0x0

move-result-object v0

.line 110

const-string v1,"firstTimeRun"

invoke-interface {v0, v1,v3, v4}, Landroid/content/SharedPreferences;->getLong(Ljava/lang/String;J)J

move-result-wide v1 #获取首次启动时间

.line 112

cmp-long v1, v1, v3 #判断配置文件中的启动时间是否为空

if-nez v1, :cond_0

.line 113

invoke-interface {v0},Landroid/content/SharedPreferences;->edit()Landroid/content/SharedPreferences$Editor;#准备写入数据

move-result-object v0

.line 114

const-string v1,"firstTimeRun"

const-wide/16 v2, 0x1

invoke-interface {v0, v1,v2, v3},Landroid/content/SharedPreferences$Editor;->putLong(Ljava/lang/String;J)Landroid/content/SharedPreferences$Editor;

#写入首次启动时间

.line 115

invoke-interface {v0}, Landroid/content/SharedPreferences$Editor;->commit()Z#提交修改

.line 116

iget-object v0, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

invoke-static {v0},Lcom/tencent/mobileqq/activity/SplashActivity;->access$100(Lcom/tencent/mobileqq/activity/SplashActivity;)V

.line 118

:cond_0

iget-object v0, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

invoke-virtual {v0},Lcom/tencent/mobileqq/activity/SplashActivity;->finish()V #结束闪屏

.line 119

new-instance v0, Landroid/content/Intent;

iget-object v1, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

const-class v2,Lcom/tencent/mobileqq/activity/HomeActivity;

invoke-direct {v0, v1,v2}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

#构造一个HomeActivity对象

.line 120

iget-object v1, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

invoke-virtual {v1},Lcom/tencent/mobileqq/activity/SplashActivity;->getIntent()Landroid/content/Intent;

move-result-object v1

const-string v2,"selfuin"

invoke-virtual {v1, v2},Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;

move-result-object v1

.line 121

invoke-static {v1},Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z

move-result v1

if-nez v1, :cond_1

.line 123

iget-object v1, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

invoke-virtual {v1},Lcom/tencent/mobileqq/activity/SplashActivity;->getIntent()Landroid/content/Intent;

move-result-object v1

invoke-virtual {v0, v1},Landroid/content/Intent;->putExtras(Landroid/content/Intent;)Landroid/content/Intent;

.line 125

:cond_1

iget-object v1, p0,Lly;->a:Lcom/tencent/mobileqq/activity/SplashActivity;

invoke-virtual {v1, v0},Lcom/tencent/mobileqq/activity/SplashActivity;->startActivity(Landroid/content/Intent;)V#启动HomeActivity

.line 128

:cond_2

return-void

.end method

.line 166

:cond_a

new-instance v0,Landroid/content/Intent;

const-string v1,"com.tencent.mobileqq.action.LOGIN"

invoke-direct {v0, v1},Landroid/content/Intent;-><init>(Ljava/lang/String;)V

const/high16 v1, 0x4

invoke-virtual {v0, v1},Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;

move-result-object v0

const/16 v1, 0x3e8

invoke-virtual {p0, v0,v1}, Lcom/tencent/mobileqq/activity/HomeActivity;->startActivityForResult(Landroid/content/Intent;I)V

goto :goto_3

在“AndroidMenifest.xml”文件中可以发现 "com.tencent.mobileqq.action.LOGIN"对应的就是LoginActivity,打开“LoginActivity.smali”文件,直接看登陆按钮监听器代码吧,同样,代码老长的,只上关键部分:

.method public onClick(Landroid/content/DialogInterface;I)V

.locals 5

.parameter

.parameter

.prologue

const/4 v1, -0x1

.line 811

iget v0, p0,Lcom/tencent/mobileqq/activity/LoginActivity;->a:I

if-eq v0, v1, :cond_3

…………

.line 836

:cond_2

invoke-virtual {v0},Lhf;->notifyDataSetChanged()V

.line 837

iget-object v0, p0,Lcom/tencent/mobileqq/activity/LoginActivity;->e:Landroid/widget/CheckBox;

invoke-virtual {v0},Landroid/widget/CheckBox;->isChecked()Z

move-result v0

if-eqz v0, :cond_3

.line 838

.line 839

invoke-virtual {v0, v2},Lcom/tencent/mobileqq/persistence/EntityManagerFactory;->build(Ljava/lang/String;)Landroid/database/sqlite/SQLiteOpenHelper;

move-result-object v1

invoke-virtual {v1},Landroid/database/sqlite/SQLiteOpenHelper;->getWritableDatabase()Landroid/database/sqlite/SQLiteDatabase;

move-result-object v1

.line 840

const-string v2,"select name from sqlite_master where type=\"table\" and namelike \"mr_%\""

const/4 v3, 0x0

invoke-virtual {v1, v2,v3}, Landroid/database/sqlite/SQLiteDatabase;->rawQuery(Ljava/lang/String;[Ljava/lang/String;)Landroid/database/Cursor;

move-result-object v2

.line 844

:goto_0

invoke-interface {v2},Landroid/database/Cursor;->moveToNext()Z

move-result v3

if-eqz v3, :cond_4

.line 845

const/4 v3, 0x0

invoke-interface {v2, v3},Landroid/database/Cursor;->getString(I)Ljava/lang/String;

move-result-object v3

.line 846

invoke-static {v3},Lcom/tencent/mobileqq/persistence/TableBuilder;->dropSQLStatement(Ljava/lang/String;)Ljava/lang/String;

move-result-object v3

invoke-virtual {v1, v3},Landroid/database/sqlite/SQLiteDatabase;->execSQL(Ljava/lang/String;)V

goto :goto_0

:catch_0

move-exception v0

.line 856

:cond_3

:goto_1

return-void

.line 848

:cond_4

new-instance v2,Lcom/tencent/mobileqq/data/RecentUser;

invoke-direct {v2},Lcom/tencent/mobileqq/data/RecentUser;-><init>()V

invoke-virtual {v2},Lcom/tencent/mobileqq/data/RecentUser;->getTableName()Ljava/lang/String;

move-result-object v2

invoke-static {v2},Lcom/tencent/mobileqq/persistence/TableBuilder;->dropSQLStatement(Ljava/lang/String;)Ljava/lang/String;

move-result-object v2

invoke-virtual {v1, v2},Landroid/database/sqlite/SQLiteDatabase;->execSQL(Ljava/lang/String;)V

.line 850

invoke-virtual {v0},Lcom/tencent/mobileqq/persistence/EntityManagerFactory;->close()V

:try_end_0

.catchLjava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

goto :goto_1

.end method

这段代码注释我就不写了,大家自己看看也能明白,它在执行一条“select name from sqlite_master where type=\"table\" andname like \"mr_%\"”SQL语句,作用就是查询表中所有以“mr_”打头的表名,这在Sqlite命令行下输入“.tables mr_%”功能是一样的。看来,TX保存信息是使用的Sqlite.。

分析到这里,有必要对Android的存储机制先有些简单的了解。在Android中,信息的存储有以下几种,第一类存储为普通的文件存储,通过JAVA提供的IO库对文件读取与写入,这与其它的语言或平台是一样的。显然,由于它直接将数据暴露给用户,这种存储机制的安全性是最低的。第二类是Android中提供的一个私有数据存储类“SharedPerferences”,它提供了简单的键值对来对数据进行的存储,上次分析的360手机卫士就是用这种方法保存数据,这个类存储的数据只能被软件自身访问(ROOT过的手机除外),对数据安全性本身进行了加强。第三类是SQLite数据库存储,有过开发经验的朋友可能都认识它,它是一个轻量级的关系型数据库,现在各大平台上应用都很广泛了,在Android系统中,它作为了一个标准数据库的存在。第四类是ContentProvider方式存储,在第二类与第三类数据在存储的数据都是程序私有的,然而新的问题是两个或多个程序有时候可能需要进行数据交换,如同一个公司产品的无缝结合等,解决这个问题就要靠ContentProvider了,一个ContentProvider接口实现了一套标准的方法接口,应用程序可以通过实现ContentProvider接口将自己的数据暴露出去,这样就做到了选择性的数据开放。第五类就是网络存储了,也就是通过网络来实现对数据的存储与获取,此类存储一般作为软件的附加功能的多。

发表评论

登录后才能评论