吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4223|回复: 6
收起左侧

[会员申请] 申请会员ID:韩龙【申请通过】

[复制链接]
吾爱游客  发表于 2015-3-21 23:39
1、申 请 I D:韩龙
2、个人邮箱:273229615@qq.com
3、原创技术文章:反编译修改破解一款APK收费注册软件,之前按各种客户要求破解了很多APK,
去年开淘宝的时候给一位客户修改一款APK,结果那傢伙拿去诈骗,害我查水表,现在闲着没事,入坛深造。特地申请一个ID
这里有一款是之前给客户录影的视频,自己感觉这个没啥技术含量,其他的我也没有什么笔记,望通过。

图片是自己之前保留的APK备份,有些是修改下文字图片,有些是破解,有些伪装手机信息,稍微高级点的就是替换原来算法或者接入自己后台管理。
1.png


视频以上次百度网盘:http://pan.baidu.com/s/1hqreoPQ


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2015-3-30 16:41
来个技术帖子分析吧。
吾爱游客  发表于 2015-3-30 23:52
Hmily 发表于 2015-3-30 16:41
来个技术帖子分析吧。

分析“讯了个雷”APK写脱机申请一天独用迅雷VIP,本来想通过之后才发给坛友用的,现在分析一下过程,用易语言写出来吧。
先来个程序图

1.png

1,APK安装在BlueStacks模拟器上面,之后进入程序前,随便开启一个截包软件,这里我用的是“smsniff2.0最新汉化汉化”,小巧绿化。
2.png
2,随后我们紧跟着开启软件就好,看看APK都发了什么提交出去。
3.png
获取免费VIP列表,这个是所有用户进入都可以看到的VIP列表,非独享,而且查看密码要点广告下载软件,很烦人,
发出去的提交我都整理出来了。独享的是判断了模拟器的ID,写脱机或者伪装模拟器信息估计也可以,觉得写易脱机更快,就没有针对APK做修改了,
就可以突破一个人用多个1天的迅雷VIP,不然用免费的那些会经常挤下线。


提交的链接地址均为:http://120.24.231.37:81/XunLeiWebService.asmx

免费VIP列表内容:<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetXunLeiVipList xmlns="http://tempuri.org/"><clientkey>GudorenXunLeiVipV100</clientkey></GetXunLeiVipList></soap:Body></soap:Envelope>
申请一人一号内容:<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><OneUserNameApply xmlns="http://tempuri.org/"><clientkey>GudorenXunLeiVipV100</clientkey><androidid>824F55CEA5DFC1AD</androidid></OneUserNameApply></soap:Body></soap:Envelope>
查看一人一号内容:<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetOneUserNameList xmlns="http://tempuri.org/"><clientkey>GudorenXunLeiVipV100</clientkey><androidid>824F55CEA5DFC1AD</androidid></GetOneUserNameList></soap:Body></soap:Envelope>

判断的就是红色文字中的那部分。用什么ID申请的就用什么ID查看。
随后就自己写了一个易语言,以为之前是自己下电影看,自己用的
也不像弄的太强大,免得给和谐了,就写的简单点,自己比较懒,基本是调试输出查看,可以用就好了,
照顾坛友,写了一个编辑框显示出来编译给没有易语言的用。

界面如下。修改框中内容即可轻松修改安卓ID申请另一个独用一天账号。
5.png
[HTML] 纯文本查看 复制代码
.版本 2
.支持库 spec

.子程序 _按钮1_被单击
.局部变量 返回, 字节集
.局部变量 返回文本, 文本型
.局部变量 分割文本, 文本型, , "0"
.局部变量 i, 整数型
.局部变量 分割文本2, 文本型, , "0"
.局部变量 j, 整数型
.局部变量 提交内容, 文本型

编辑框1.加入文本 (“=========以下是自己独占VIP=======” + #换行符)
提交内容 = 子文本替换 (#自己VIP, “iiiidddd”, 编辑框2.内容, , , 真)
返回 = 网页访问底层 (“http://120.24.231.37:81/XunLeiWebService.asmx”, “POST”, , , , “Content-Type: text/xml;charset=utf-8” + #换行符 + “SOAPAction: http://tempuri.org/GetOneUserNameList” + #换行符 + “User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.0.4; GT-I9300 Build/IMM76D)”, , , , , , , , , 到字节集 (提交内容))


返回文本 = 编码_Utf8到Ansi (返回)
' 调试输出 (返回文本)
分割文本 = 分割文本 (返回文本, “GetOneUserNameListResult”, )
.计次循环首 (取数组成员数 (分割文本), i)
    .判断开始 (寻找文本 (分割文本 [i], “PassWord”, , 假) > 0)
        ' 调试输出 (分割文本 [i])
        分割文本 [i] = 子文本替换 (分割文本 [i], #引号, , , , 真)
        分割文本2 = 分割文本 (分割文本 [i], “},{”, )
        .计次循环首 (取数组成员数 (分割文本2), j)
            分割文本2 [j] = 子文本替换 (子文本替换 (分割文本2 [j], “>[{”, , , , 真), “}]</”, , , , 真)
            调试输出 (分割文本2 [j])
            编辑框1.加入文本 (分割文本2 [j] + #换行符)
        .计次循环尾 ()
    .默认

    .判断结束

.计次循环尾 ()
调试输出 (“=========完美分割线=======”)
编辑框1.加入文本 (“================” + #换行符)
编辑框2.禁止 = 假

.子程序 _按钮2_被单击
.局部变量 返回, 字节集
.局部变量 返回文本, 文本型
.局部变量 分割文本, 文本型, , "0"
.局部变量 i, 整数型
.局部变量 分割文本2, 文本型, , "0"
.局部变量 j, 整数型

编辑框1.加入文本 (“=========以下是免费12小时VIP=======” + #换行符)
返回 = 网页访问底层 (“http://120.24.231.37:81/XunLeiWebService.asmx”, “POST”, , , , “Content-Type: text/xml;charset=utf-8” + #换行符 + “SOAPAction: http://tempuri.org/GetXunLeiVipList” + #换行符 + “User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.0.4; GT-I9300 Build/IMM76D)”, , , , , , , , , 到字节集 (#VIP列表))

返回文本 = 编码_Utf8到Ansi (返回)
' 调试输出 (返回文本)
分割文本 = 分割文本 (返回文本, “GetXunLeiVipListResult”, )
.计次循环首 (取数组成员数 (分割文本), i)
    .判断开始 (寻找文本 (分割文本 [i], “PassWord”, , 假) > 0)
        调试输出 (分割文本 [i])
        分割文本 [i] = 子文本替换 (分割文本 [i], #引号, , , , 真)
        分割文本2 = 分割文本 (分割文本 [i], “},{”, )
        .计次循环首 (取数组成员数 (分割文本2), j)
            分割文本2 [j] = 子文本替换 (子文本替换 (分割文本2 [j], “>[{”, , , , 真), “}]</”, , , , 真)
            调试输出 (分割文本2 [j])
            编辑框1.加入文本 (分割文本2 [j] + #换行符)
        .计次循环尾 ()
    .默认

    .判断结束

.计次循环尾 ()
' 调试输出 (编码_Utf8到Ansi (返回))
' 调试输出 (到文本 ())
编辑框1.加入文本 (“=========完美分割线=======” + #换行符)
调试输出 (“================”)


.子程序 _按钮3_被单击
.局部变量 返回, 字节集
.局部变量 返回文本, 文本型
.局部变量 提交内容, 文本型

提交内容 = 子文本替换 (#申请VIP, “iiiidddd”, 编辑框2.内容, , , 真)

返回 = 网页访问底层 (“http://120.24.231.37:81/XunLeiWebService.asmx”, “POST”, , , , “Content-Type: text/xml;charset=utf-8” + #换行符 + “SOAPAction: http://tempuri.org/OneUserNameApply” + #换行符 + “User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.0.4; GT-I9300 Build/IMM76D)”, , , , , , , , , 到字节集 (提交内容))

返回文本 = 编码_Utf8到Ansi (返回)
调试输出 (返回文本)
.如果 (返回文本 ≠ “”)
    编辑框1.加入文本 (“申请成功!请查看自己12小时VIP!” + #换行符)

.否则

.如果结束

编辑框2.禁止 = 真
调试输出 (“================”)

附件打包了软件和源码。可自行下载。
百度网盘下载链接:http://pan.baidu.com/s/1kTMM6Bt
4.png
吾爱游客  发表于 2015-3-31 00:52
Hmily 发表于 2015-3-30 16:41
来个技术帖子分析吧。

分析一款电话轰炸机写注册机
1.png
点激活要求根据IMEI来获取激活码。

下面进入正题
1,我们用解压缩WINRAR软件打开APK,提取classes.dex文件。
Android逆向助手_v2.0对classes.dex转JAR处理。查看并找到反编译后的JAVA代码。
2.png


注册核心算法代码:
[Java] 纯文本查看 复制代码
 public void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903041);
    this.lvBTDevices = ((ListView)findViewById(2131034132));
    this.adtDevices = new ArrayAdapter(this, 17367043, this.lstDevices);
    this.lvBTDevices.setAdapter(this.adtDevices);
    this.btnCall = ((Button)findViewById(2131034129));
    this.btnClear = ((Button)findViewById(2131034130));
    this.btnAdd = ((Button)findViewById(2131034121));
    this.etTelNum = ((EditText)findViewById(2131034120));
    this.layoutRoot = ((LinearLayout)findViewById(2131034118));
    this.txtgdtime = ((EditText)findViewById(2131034122));
    this.txtjgtime = ((EditText)findViewById(2131034124));
    this.txtci = ((EditText)findViewById(2131034127));
    this.btnEnable = ((Button)findViewById(2131034131));
    this.btnEnable.setOnClickListener(this.ls);
    this.btnCall.setOnClickListener(this.ls);
    this.btnAdd.setOnClickListener(this.ls);
    this.btnClear.setOnClickListener(this.ls);
    this.layoutRoot.setOnClickListener(this.ls);
    this.share = getSharedPreferences("perference", 0);
    this.imm = ((InputMethodManager)getSystemService("input_method"));
    Log.w("ActvTel", " -- onCreate");
    Intent localIntent = getIntent();
    this.telNum = localIntent.getStringExtra("telNum");
    this.isGoBack = localIntent.getBooleanExtra("isGoBack", false);
    if (this.isGoBack)
    {
      Log.w("ActvTel", " -- isGoBack --> finish()");
      finish();
    }
    while (true)
    {
      return;
      this.ab = this.share.getString("Imei", "");
      String str = ((TelephonyManager)getSystemService("phone")).getDeviceId().toUpperCase().replace('A', '5').replace('B', '5').replace('C', '5').replace('D', '5').replace('E', '5').replace('F', '5').replace('G', '5').replace('H', '5').replace('J', '5').replace('K', '5').replace('L', '5').replace('M', '5').replace('N', '5').replace('O', '5').replace('P', '5').replace('Q', '5').replace('R', '5').replace('S', '5').replace('T', '5').replace('U', '5').replace('V', '5').replace('W', '5').replace('X', '5').replace('Y', '5').replace('Z', '5');
      int i = 0;
      int j = 0;
      int k;
      if (j >= str.length())
        k = 2011 + i * 3;
      try
      {
        int n = Integer.parseInt(this.ab.trim());
        m = n;
        if (k != m)
          continue;
        this.btnEnable.setVisibility(8);
        this.enable = "1";
        return;
        i += Integer.parseInt(str.substring(j, j + 1));
        j++;
      }
      catch (Exception localException)
      {
        while (true)
          int m = 0;
      }
    }
  }



整理后是:
1,IMEI数字全部转成数字5
2,IMEI循环累加
3,注册码 = 2011 + IMEI循环累加数 * 3;


3.png
.计次循环首 (取文本长度 (编辑框1.内容), i)
    累计加数 = 累计加数 + 到整数 (取文本右边 (取文本左边 (编辑框1.内容, i), 1))
.计次循环尾 ()
编辑框2.内容 = 到文本 (2011 + 3 × 累计加数)


吾爱游客  发表于 2015-3-31 01:59
Hmily 发表于 2015-3-30 16:41
来个技术帖子分析吧。

破解商丘路考仪
这一款也是去年开淘宝的时候接的单,客户跟我介绍说,有一家淘宝可以写注册机600元。
最后我分析完之后跟他说能写成手机APK手机用的注册机500元,嫌价格高和麻烦没做。以为每次客户向他买的时候,他也要自己修改一次。其实当时我建议去掉原来验证算法,改成网络验证应该会好点。
最后直接做了个破解版的。好像是收费200还是100,忘记了。

以下切入破解正题。
1,依旧逆向助手转JAR,查看分析软件JAVA代码。(因为直接反编译SMALI文件代码不宜分析)

2,启动软件后弹出
1.png
2.png
这关键出错的可作超找关键点。
3.找到关键地方
3.png
启动软件的时候,就做了判断
      Log.i("Index_f2_Activity", "onCreate; " + this.macAddress + "; ");
      if (!this.themeService.is_reg_ser(this.macAddress))
      {
        Toast.makeText(this, "抱歉,该软件未经授权,暂时无法使用.", 1).show();
        finish();
      }

传入MACADDRESS.is_reg_ser这个函数
4.png
意思大概是读取apk下面accets文件夹下面的export_ser文件。
我们打开一下这文件内容如下
6.png
很明显,就应该是注册码。作者是把注册码算出来后放到这文件里面,每出售一个软件就封装添加一个注册码进去。
[Java] 纯文本查看 复制代码
    for (int j = 0; ; j++)
    {
      if (j >= localArrayList2.size())
      {
        return false;
        localArrayList1.add(str1);
        break;
        label143: String str2 = (String)localArrayList1.get(i);
        ThreeDes localThreeDes = new ThreeDes();
        if ((str2 != null) && (str2.trim().length() > 0))
          localArrayList2.add(localThreeDes.decrypt(str2));
        i++;
        break label101;
      }
      if (((String)localArrayList2.get(j)).equals(paramString))
        return true;
    }
  }

这段代码的意思就通过DES解密之后跟传入的MAC地址做比较。

(因为i刚开始接触桌面编程的时候用的是易,所以基本没学其他编程语言,但都基本初略能看懂,所以我查找了好多个DES算法的易语言,结果得到的跟JAVA的结果不同,我自己也没自己去写过。
但是可以用JAVA自己写一个APK,就可以把算法算出来,因为JAVA引用DES就几句话,很方便。也就有了前面跟客户说的可以写一个手机APK的注册机)

思路清晰了。所以就这个函数里面的return false;都改为true,就破解了。
4,把APK反编译成smali文件,一遍修改后打包回去。
8.png
5,反编译后找到smali\com\lilin\gps\service下的ThemeService.smali文件,打开定位到关键点
[Asm] 纯文本查看 复制代码
.method public is_reg_ser(Ljava/lang/String;)Z
    .locals 12
    .parameter "macAddress"
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/lang/Exception;
        }
    .end annotation

    .prologue
    .line 295
    const/4 v4, 0x0

    .line 296
    .local v4, flag:Z
    if-eqz p1, :cond_0

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

    move-result-object v10

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

    move-result v10

    if-nez v10, :cond_1

    .line 297
    :cond_0
    const/4 v4, 0x0

    move v5, v4

    .line 329
    .end local v4           #flag:Z
    .local v5, flag:I
    :goto_0
    return v5

    .line 300
    .end local v5           #flag:I
    .restart local v4       #flag:Z
    :cond_1
    iget-object v10, p0, Lcom/lilin/gps/service/ThemeService;->context:Landroid/content/Context;

    invoke-virtual {v10}, Landroid/content/Context;->getAssets()Landroid/content/res/AssetManager;

    move-result-object v10

    const-string v11, "export_ser"

    invoke-virtual {v10, v11}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream;

    move-result-object v9

    .line 301
    .local v9, stream:Ljava/io/InputStream;
    new-instance v2, Ljava/io/BufferedReader;

    new-instance v10, Ljava/io/InputStreamReader;

    .line 302
    const-string v11, "GBK"

    invoke-static {v11}, Ljava/nio/charset/Charset;->forName(Ljava/lang/String;)Ljava/nio/charset/Charset;

    move-result-object v11

    invoke-direct {v10, v9, v11}, Ljava/io/InputStreamReader;-><init>(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V

    .line 301
    invoke-direct {v2, v10}, Ljava/io/BufferedReader;-><init>(Ljava/io/Reader;)V

    .line 303
    .local v2, bf:Ljava/io/BufferedReader;
    new-instance v8, Ljava/util/ArrayList;

    invoke-direct {v8}, Ljava/util/ArrayList;-><init>()V

    .line 304
    .local v8, sers:Ljava/util/List;,"Ljava/util/List<Ljava/lang/String;>;"
    const-string v7, ""

    .line 305
    .local v7, ser:Ljava/lang/String;
    :goto_1
    invoke-virtual {v2}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String;

    move-result-object v7

    if-nez v7, :cond_3

    .line 308
    invoke-virtual {v2}, Ljava/io/BufferedReader;->close()V

    .line 309
    invoke-virtual {v9}, Ljava/io/InputStream;->close()V

    .line 310
    invoke-interface {v8}, Ljava/util/List;->size()I

    move-result v10

    if-lez v10, :cond_2

    .line 311
    const-string v0, ""

    .line 312
    .local v0, address:Ljava/lang/String;
    new-instance v1, Ljava/util/ArrayList;

    invoke-direct {v1}, Ljava/util/ArrayList;-><init>()V

    .line 313
    .local v1, addresses:Ljava/util/List;,"Ljava/util/List<Ljava/lang/String;>;"
    const/4 v6, 0x0

    .local v6, i:I
    :goto_2
    invoke-interface {v8}, Ljava/util/List;->size()I

    move-result v10

    if-lt v6, v10, :cond_4

    .line 321
    const/4 v6, 0x0

    :goto_3
    invoke-interface {v1}, Ljava/util/List;->size()I

    move-result v10

    if-lt v6, v10, :cond_6

    .end local v0           #address:Ljava/lang/String;
    .end local v1           #addresses:Ljava/util/List;,"Ljava/util/List<Ljava/lang/String;>;"
    .end local v6           #i:I
    :cond_2
    move v5, v4

    .line 329
    .restart local v5       #flag:I
    goto :goto_0

    .line 306
    .end local v5           #flag:I
    :cond_3
    invoke-interface {v8, v7}, Ljava/util/List;->add(Ljava/lang/Object;)Z

    goto :goto_1

    .line 314
    .restart local v0       #address:Ljava/lang/String;
    .restart local v1       #addresses:Ljava/util/List;,"Ljava/util/List<Ljava/lang/String;>;"
    .restart local v6       #i:I
    :cond_4
    invoke-interface {v8, v6}, Ljava/util/List;->get(I)Ljava/lang/Object;

    move-result-object v7

    .end local v7           #ser:Ljava/lang/String;
    check-cast v7, Ljava/lang/String;

    .line 315
    .restart local v7       #ser:Ljava/lang/String;
    new-instance v3, Lcom/lilin/gps/util/ThreeDes;

    invoke-direct {v3}, Lcom/lilin/gps/util/ThreeDes;-><init>()V

    .line 316
    .local v3, des1:Lcom/lilin/gps/util/ThreeDes;
    if-eqz v7, :cond_5

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

    move-result-object v10

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

    move-result v10

    if-lez v10, :cond_5

    .line 317
    invoke-virtual {v3, v7}, Lcom/lilin/gps/util/ThreeDes;->decrypt(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    .line 318
    invoke-interface {v1, v0}, Ljava/util/List;->add(Ljava/lang/Object;)Z

    .line 313
    :cond_5
    add-int/lit8 v6, v6, 0x1

    goto :goto_2

    .line 322
    .end local v3           #des1:Lcom/lilin/gps/util/ThreeDes;
    :cond_6
    invoke-interface {v1, v6}, Ljava/util/List;->get(I)Ljava/lang/Object;

    move-result-object v0

    .end local v0           #address:Ljava/lang/String;
    check-cast v0, Ljava/lang/String;

    .line 323
    .restart local v0       #address:Ljava/lang/String;
    invoke-virtual {v0, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v10

    if-eqz v10, :cond_7

    .line 324
    const/4 v4, 0x1

    move v5, v4

    .line 325
    .restart local v5       #flag:I
    goto :goto_0

    .line 321
    .end local v5           #flag:I
    :cond_7
    add-int/lit8 v6, v6, 0x1

    goto :goto_3
.end method



    :goto_0
    return v5

中间给V5赋值为1就可以了
    const/4 v5, 0x1

6.选中修改好了的反编译文件夹。打包回APK。
9.png


7,打包完,要在手机上运行,还得给APK重新签一下名。
11.png
8,试运行,一切OK,完工!
12.png
Hmily 发表于 2015-3-31 11:42
ID:韩龙
邮箱:273229615@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。
韩龙 发表于 2015-3-31 19:04
前往报道!谢谢。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 18:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表