Android作假大作战之你真的相信鲁大师、安兔兔评测跑分吗?

前言:本文仅针对少部分中低端Android(山寨)机,请勿对各大厂商对号入座~不是鼓励大家作假,只是让大家对手机评测的水分有更深的了解~

现在国内Android市场如火如荼,Android机的价格从几百到几千不等,差异还是比较大的。我们经常能听到有人巴拉巴拉说自己几百买了个多好多好的手机,CPU xxx,内存 xxx,像素 xxx,跑分完爆某米几条街,比某米实惠强大太多了。那么我们今天就来扒一拔这些数据一定是真的吗?这些跑分排名一定准确吗?

小白型作假

先从我们最关心的CPU信号来看:
一般可以从我们手机的设置--关于手机中选项中查看到当前的cpu型号、主频、核数等信息,如下所示:


这部分的作假有一种最简单愚蠢的方法,直接在当前Activity找到该String将其修改掉,设置中的这些菜单项一般都是Preference的子类,我们可以在xml文件中找到其相应summarytitle的字符即可,如下:

            android:summary="@string/cpu_setting_summary"
            android:title="@string/cp_setting_title" 

修改后的效果图:


这很简单吧?相信刚接触Android一天的同学都能明白。但是为什么又说愚蠢呢?很明显,这要修改的话只能修改掉当前Activity的字符,万一其他地方也有读取显示cpu信息,就会造成显示不同信息的冲突,另外当用户使用第三方apk评测的时候也会瞬间原形毕露,所以这样的修改方法可以直接pass。

进阶型作假

上面提及了第三APK评测时的作假问题,那我们怎样才能修改使得第三方的APK也能"掩护"我们作假呢?其实有了思路就会发现非常简单。因为作假一般都是在rom层开发的时候考虑的,所以我们可以直接修改framework框架层的东西。最终显示在鲁大师、安兔兔等跑分软件上的信息本质肯定也是一个TextView,但我们又不能去修改鲁大师、安兔兔等代码,所以退而求其次,我们修改framework层中的TextView.java(frameworks/base/core/java/android/widget/TextView.java),大致思路可以参考下面的代码:

private void setText(CharSequence text, BufferType type,
                         boolean notifyBefore, int oldlen) {
        if (text == null) {
            text = "";
        }
        String packageName = getContext().getPackageName();

        if (packageName.equals("com.antutu.ABenchMark")
                || packageName.equals("com.cpuid.cpu_z")
                || packageName.equals("com.primatelabs.geekbench")) {

            String str1 = text.toString();
            if (str1.contains("hahaha")) {
                text = "lalalala";
            }
            
        }
    }
}

我们直接在框架层TextView的setText方法最前面添加了一段逻辑,判断一下当前应用包名的及显示的字符名是否符合我们需要作假的评测软件,如果满足直接替换作假信息的字符,当然这里只是最间的字符替换,其他作假情况也完全可以按以上思路直接修改framework中的源码!这样的话当第三方APP运行在我们的系统中时就能"掩护"我们了~但是,这种方案也有一个致命的缺点,万一用户不用鲁大师呢?而是用360、腾讯或者其他第三方评测应用呢?难道我们还要一个一个包名类名的添加至setText()中?这显然不符和设计代码的原理。

终极作假

这里以手机内置存储空间为例,作假让其在任何时候都能向外界提供"假信息"。手机的存储空间并不是直接在系统上层(这里指application、framework层)上报的,而是从底层(kernel、hal、jni层)传递给上层处理。所以为了一劳永逸,我们直接在底层动手!在其向上层传递的时候,我们就改变它的部分信息,不必再考虑上层使用什么第三方app。
观察系统源码libcore/luni/src/main/native/libcore_io_Posix.cpp,我们可以找到此函数:

static jobject Posix_statvfs(JNIEnv* env, jobject, jstring javaPath) {
    ScopedUtfChars path(env, javaPath);
    if (path.c_str() == NULL) {
        return NULL;
    }
    struct statvfs sb;
    int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
    if (rc == -1) {
        throwErrnoException(env, "statvfs");
        return NULL;
    }
    //return makeStructStatVfs_fake(env, sb, false);
    return makeStructStatVfs(env, sb);
}

最后的return makeStructStatVfs(env, sb);便是向上层传递的存储空间信息,因此我们直接模仿makeStructStatVfs(env, sb)自己写一个makeStructStatVfs_fake(env, sb, false)函数,将此return给上层:

static jobject makeStructStatVfs_fake(JNIEnv* env, const struct statvfs& sb, bool internal) {
    jlong f_blocks;
    jlong f_bfree;
    jlong f_bavail;
    int value = 0;
    jlong f_blocks_temp ;
    int size =0 ;
    //[CDS]Libcore_io_Posix bsize:4096
    //[CDS]Libcore_io_Posix frsize:4096
    //[CDS]Libcore_io_Posix blocks:207369
    //[CDS]Libcore_io_Posix bfree:189725
    //[CDS]Libcore_io_Posix bavail:189725
    size = property_getInt("fake_system_rom_size", size);
        if(internal) { //internal storage
            value = property_getInt("internal_fake_rom_size", 0);
        } else { //phone storage
            value = property_getInt("phone_fake_rom_size", 0);
        }
    
        if(value == 0) {
            f_blocks = sb.f_blocks;
            f_bfree = sb.f_bfree;
            f_bavail = sb.f_bavail;
        } else {
            f_blocks = (jlong)(((jlong)value * 256 * 4096) / sb.f_bsize); 
        f_blocks_temp = (jlong)(((jlong)(value - size) * 256 * 4096) / sb.f_bsize);
            f_bfree = (jlong)((jfloat)((jfloat) f_blocks_temp / sb.f_blocks ) * sb.f_bfree );
            f_bavail = (jlong)((jfloat)((jfloat) f_blocks_temp / sb.f_blocks) * sb.f_bavail);
        }

        static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
            "(JJJJJJJJJJJ)V");
        return env->NewObject(JniConstants::structStatVfsClass, ctor,
                          static_cast<jlong>(sb.f_bsize),
                          static_cast<jlong>(sb.f_frsize),
                          static_cast<jlong>(f_blocks),
                          static_cast<jlong>(f_bfree),
                          static_cast<jlong>(f_bavail),
                          static_cast<jlong>(sb.f_files),
                          static_cast<jlong>(sb.f_ffree),
                          static_cast<jlong>(sb.f_favail),
                          static_cast<jlong>(sb.f_fsid),
                          static_cast<jlong>(sb.f_flag),
                          max_name_length);
}

看似一长段代码,其实就只是将sb.f_bsizesb.f_bfreesb.f_bavail替换成我们作假的大小和数量。看一下效果图:
作假前


作假后





除了这些,用户肯定还关心像素吧?这其实也没什么难度。camera像素作假一般会做到二千万像素,五千万也不是不可能,如果是仅仅针对工具检测推荐修改的地方为:frameworks\base\core\java\android\hardware\Camera.java中的getSupportedPictureSizes()方法:

public List<Size> getSupportedPictureSizes() {
            String str = get((mStereo3DMode ? KEY_STEREO3D_PRE : "") + KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
            if(DisplayManagerGlobal.getCurrentFakeProcess()){
                ArrayList<Size> sizeList = splitSize(str);
                Size large_size = sizeList.get(sizeList.size() - 1);
                if(large_size.width * large_size.height > 2560 * 1920) str += ",4608x3456";
            }
            return splitSize(str);
}

最后在此说明本文并不是作假教学,也没针对任何手机!只是想让大家谨慎购机,让大家明白,良辰有一百种作假的方法,而你却无可奈何~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,488评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 为什么我们总是尝试养成一些好习惯,准备坚持做一件事,可遗憾的是往往大家都不能坚持下来,原因在哪?怎么样才能让自己坚...
    黄河飞杜阅读 264评论 0 0
  • 语言是一把双刃剑:传递温暖和冰冷的工具,愿你永远不要使用冰冷那一刃。 首先问大家两个问题:你们和爱人提过分手吗?你...
    小丫小丫阅读 333评论 0 0
  • 是什么: npm 是使用别人代码与分享自己代码(代码共享)的一种开发方式,同时它可以轻松的管理同一份代码的不同版本...
    a_pioneer阅读 494评论 0 0