吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 21411|回复: 23
收起左侧

[Android 原创] 对帖子 [还能不能有点职业道德]菜鸟学破解---破解辅助ID注册码 破解的完善

  [复制链接]
小灰灰~ 发表于 2017-12-21 14:05
看了[还能不能有点职业道德]菜鸟学破解---破解辅助ID注册码这篇帖子后,发现楼主使用的工具破解的,而且评论区有一些人有疑惑,本着分享的精神写了这篇文章,
原贴地址: https://www.52pojie.cn/thread-677470-1-1.html


这篇文章只适合和我一样的新手玩家!!!
[Java] 纯文本查看 复制代码
for(int n=0;n<50;n++){    	   String paramString=Integer.toString(((int)(Math.random() * 1000000000 % 100000)));
    	   SecretKeySpec localSecretKeySpec;
   		try {
   			localSecretKeySpec = new SecretKeySpec("Format2044153997".getBytes("ASCII"), "AES");
   			Cipher localCipher = Cipher.getInstance("AES");
   	        localCipher.init(1, localSecretKeySpec);
   	     
   	        System.out.println(byte2hex(localCipher.doFinal(paramString.getBytes())).toLowerCase());
   		} catch (UnsupportedEncodingException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		} catch (NoSuchAlgorithmException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		} catch (NoSuchPaddingException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		} catch (InvalidKeyException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		} catch (IllegalBlockSizeException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		} catch (BadPaddingException e) {
   			// TODO Auto-generated catch block
   			e.printStackTrace();
   		}
           
       }


private String byte2hex(byte[] paramArrayOfByte) {
		 	StringBuffer str1 = new StringBuffer();
		    for(int i=0;i<paramArrayOfByte.length;i++){
		    	
		    		String str2 = Integer.toHexString(paramArrayOfByte[i] & 0xFF);
		    		if (str2.length() == 1) {
		    			str1.append("0");
		    		}
		    		str1.append(str2);
			    
		    }
		 	
		    return new String(str1).toUpperCase();
	}
@jiangwei212 @wlpkcheng


APP下载地址: 链接: https://pan.baidu.com/s/1jHMBUWu 密码: 2333
在对该软件进行破解过程中我使用了三种方式破解,有两种方式是类似的,另一种方式是逆向出算法,并且对这款app有多个注册码的原因做出了解释。

破解过程:
1. 这个app没有进行加固,直接使用工具AndroidKiller进行反编译
1.png
2. 反编译后,出现的是smail代码,为了直观,我们先转换成java代码查看,AndroidKiller这款工具可以直接将smail代码转换成java代码
2.png
3.png
3. 查看java代码,理清逻辑关系:
直接查看onCreate方法:
[Java] 纯文本查看 复制代码
 public void onCreate(Bundle paramBundle)
  {
    this.key = 2004;
    super.onCreate(paramBundle);
    SharedPreferences localSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    boolean bool = localSharedPreferences.getBoolean("F1501993228010", false);
    if (localSharedPreferences.getBoolean("F1501993240355", false))
    {
      enter();
      return;
    }
    this.temp = localSharedPreferences.getString("sss", "");
    Date localDate = new Date();
    long l1 = -1;
    long l2 = -1;
    try
    {
      l3 = Long.parseLong(de(this.temp));
      l1 = l3;
    }
    catch (Exception paramBundle)
    {
      long l3;
      break label93;
    }
    catch (NumberFormatException paramBundle)
    {
      label93:
      break label93;
    }
    if (bool) {
      this.temp = localSharedPreferences.getString("ttt", "");
    }
    try
    {
      l3 = Long.parseLong(de(this.temp));
      l2 = l3;
    }
    catch (Exception paramBundle)
    {
      LinearLayout localLinearLayout;
      Object localObject;
      break label129;
    }
    catch (NumberFormatException paramBundle)
    {
      label129:
      label325:
      break label129;
      enter();
      return;
    }
    if (localDate.getTime() - l1 > l2)
    {
      dia("注册码已过期!", (DialogInterface.OnClickListener)null);
      localSharedPreferences.edit().putBoolean("F1501993228010", false).commit();
      localSharedPreferences.edit().putString("sss", "").commit();
      localSharedPreferences.edit().putString("ttt", "").commit();
      this.id = localSharedPreferences.getInt("id", -1);
      if (this.id == -1)
      {
        this.id = ((int)(Math.random() * 1000000000 % 100000));
        localSharedPreferences.edit().putInt("id", this.id).commit();
      }
      localLinearLayout = new LinearLayout(this);
      localLinearLayout.setOrientation(1);
      localObject = getAssets();
      paramBundle = (InputStream)null;
    }
    try
    {
      localObject = ((AssetManager)localObject).open("background.jpg");
      paramBundle = (Bundle)localObject;
    }
    catch (IOException localIOException)
    {
      break label325;
    }
    if (paramBundle != null) {
      localLinearLayout.setBackgroundDrawable(Drawable.createFromStream(paramBundle, ""));
    }
    this.tv = new TextView(this);
    this.tv.setTextSize(20);
    this.tv.setText("此枪战爆头辅助为不止心殇9.28开发,激活需要ID密码25块&#128176;,要买加我抠抠2824130236    ___\n   /   ▲\n/ ̄  ヽ ■■\n●     ■■\nヽ___  ■■\n    )=|\n   / ||\n ∩∩__と&#65417;\n しし———┘\n");
    this.tv.append("你的ID:" + this.id);
    localLinearLayout.addView(this.tv);
    this.edit = new EditText(this);
    localLinearLayout.addView(this.edit);
    paramBundle = new Button(this);
    paramBundle.setText("复制ID");
    paramBundle.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View paramAnonymousView)
      {
        ((ClipboardManager)FAppProtect.this.getSystemService("clipboard")).setText(FAppProtect.this.id + "");
        Toast.makeText(FAppProtect.this, FAppProtect.this.id + "", 2000).show();
      }
    });
    localLinearLayout.addView(paramBundle);
    this.enter = new Button(this);
    this.enter.setText("进入");
    localLinearLayout.addView(this.enter);
    this.enter.setOnClickListener(new View.OnClickListener()
    {
      private final Date val$date;
      private final SharedPreferences val$sp;
      
      @Override
      public void onClick(View paramAnonymousView)
      {
        int i = FAppProtect.this.id / 2;
        i = FAppProtect.this.key;
        i = FAppProtect.this.key;
        paramAnonymousView = FAppProtect.de(FAppProtect.this.edit.getText().toString());
        if (paramAnonymousView == null) {
          return;
        }
        String[] arrayOfString = paramAnonymousView.split("z");
        try
        {
          Integer.parseInt(arrayOfString[0], 16);
          Toast.makeText(FAppProtect.this, "启动成功,一起去浪吧,小伙子!", 2000).show();
          paramAnonymousView = "激活成功,不止心殇告诫大家:请尊重作者也尊重自己,不要非法转载别人,否则和谐没用了不要找我&#128545;";
          if (arrayOfString.length > 1) {
            paramAnonymousView = "软件无限期使用" + FAppProtect.formatDuring(Long.parseLong(arrayOfString[1]));
          }
          FAppProtect.this.dia(paramAnonymousView, new DialogInterface.OnClickListener()
          {
            private final Date val$date;
            private final SharedPreferences val$sp;
            private final String[] val$y;
            
            @Override
            public void onClick(DialogInterface paramAnonymous2DialogInterface, int paramAnonymous2Int)
            {
              if (this.val$y.length > 1) {
                this.val$sp.edit().putBoolean("F1501993228010", true).commit();
              }
              for (;;)
              {
                try
                {
                  this.val$sp.edit().putString("ttt", FAppProtect.en(this.val$y[1])).commit();
                  FAppProtect.this.temp = ("" + this.val$date.getTime());
                }
                catch (Exception paramAnonymous2DialogInterface)
                {
                  try
                  {
                    this.val$sp.edit().putString("sss", FAppProtect.en(FAppProtect.this.temp)).commit();
                    this.val$sp.edit().putInt("id", -1).commit();
                    FAppProtect.this.enter();
                    return;
                    paramAnonymous2DialogInterface = paramAnonymous2DialogInterface;
                  }
                  catch (Exception paramAnonymous2DialogInterface)
                  {
                    continue;
                  }
                }
                this.val$sp.edit().putBoolean("F1501993240355", true).commit();
              }
            }
          });
          return;
        }
        catch (NumberFormatException paramAnonymousView)
        {
          FAppProtect.this.enter.setText("失败,点击重试!");
        }
      }
    });
    new Button(this);
    setContentView(localLinearLayout);
  }
}

在代码前几行,我发现了下面这段代码
[Java] 纯文本查看 复制代码
if (localSharedPreferences.getBoolean("F1501993240355", false))    {
      enter();
      return;
    }

如果localSharedPreferences.getBoolean("F1501993240355", false) 为真,表示激活过直接进入enter()函数,enter函数展示的就是激活后的界面,如下:
4.png
所以这段代码是我们破解的关键,有两种修改smail代码的方式,一是if (localSharedPreferences.getBoolean("F1501993240355", false)) 修改成if (localSharedPreferences.getBoolean("F1501993240355", false)),二是if (localSharedPreferences.getBoolean("F1501993240355", false))修改成if (localSharedPreferences.getBoolean("F1501993240355", true))。
4. 修改smail语法
在FAppProject.smail中oncreate方法中找到下面关键代码的对应出。(比较简单方法是查找“F1501993240355”关键字,可以快速定位
[Java] 纯文本查看 复制代码
if (localSharedPreferences.getBoolean("F1501993240355", false)){
enter();
return;
}

5.png
图中的两种方式,任意选一种都可以。


以上就是两种通过修改smail方式来达到破解的目的的方法。


5. 进行算法的逆向
点击进入按钮后触发onclick事件,对应代码是
[Java] 纯文本查看 复制代码
public void onClick(View paramAnonymousView)
      {
        int i = FAppProtect.this.id / 2;
        i = FAppProtect.this.key;
        i = FAppProtect.this.key;
        paramAnonymousView = FAppProtect.de(FAppProtect.this.edit.getText().toString());
        if (paramAnonymousView == null) {
          return;
        }
        String[] arrayOfString = paramAnonymousView.split("z");
        try
        {
          Integer.parseInt(arrayOfString[0], 16);
          Toast.makeText(FAppProtect.this, "启动成功,一起去浪吧,小伙子!", 2000).show();
          paramAnonymousView = "激活成功,不止心殇告诫大家:请尊重作者也尊重自己,不要非法转载别人,否则和谐没用了不要找我&#128545;";
          if (arrayOfString.length > 1) {
            paramAnonymousView = "软件无限期使用" + FAppProtect.formatDuring(Long.parseLong(arrayOfString[1]));
          }
          FAppProtect.this.dia(paramAnonymousView, new DialogInterface.OnClickListener()
          {
            private final Date val$date;
            private final SharedPreferences val$sp;
            private final String[] val$y;
            
            @Override
            public void onClick(DialogInterface paramAnonymous2DialogInterface, int paramAnonymous2Int)
            {
              if (this.val$y.length > 1) {
                this.val$sp.edit().putBoolean("F1501993228010", true).commit();
              }
              for (;;)
              {
                try
                {
                  this.val$sp.edit().putString("ttt", FAppProtect.en(this.val$y[1])).commit();
                  FAppProtect.this.temp = ("" + this.val$date.getTime());
                }
                catch (Exception paramAnonymous2DialogInterface)
                {
                  try
                  {
                    this.val$sp.edit().putString("sss", FAppProtect.en(FAppProtect.this.temp)).commit();
                    this.val$sp.edit().putInt("id", -1).commit();
                    FAppProtect.this.enter();
                    return;
                    paramAnonymous2DialogInterface = paramAnonymous2DialogInterface;
                  }
                  catch (Exception paramAnonymous2DialogInterface)
                  {
                    continue;
                  }
                }
                this.val$sp.edit().putBoolean("F1501993240355", true).commit();
              }
            }
          });
          return;
        }
        catch (NumberFormatException paramAnonymousView)
        {
          FAppProtect.this.enter.setText("失败,点击重试!");
        }
      }
    });

大概流程是先获取用户输入的激活码,然后调用de方法,在de方法中会调用byte2hex方法,然后判断de方法返回值是否是NULL,不是则表明输入激活码正确,大家发现么有判断激活码是否正确和给我们的id没有任何关系。
那如何获取正确的激活码呢?通过查看代码,发现有一个en函数和de函数,de是解密函数,那en就是加密函数了(虽然有en加密函数,但是没有被调用,我们可以直接查看en函数,来得到激活码,刚开始我一直研究de函数,没有发现有en加密函数,所以走了很多弯路)
6.png
涉及到的加密代码有:
[Java] 纯文本查看 复制代码
 public static String en(String paramString)
    throws Exception
  {
    if ("Format2044153997" == null) {
      return (String)null;
    }
    if ("Format2044153997".length() != 16) {
      return (String)null;
    }
    SecretKeySpec localSecretKeySpec = new SecretKeySpec("Format2044153997".getBytes("ASCII"), "AES");
    Cipher localCipher = Cipher.getInstance("AES");
    localCipher.init(1, localSecretKeySpec);
    return byte2hex(localCipher.doFinal(paramString.getBytes())).toLowerCase();
  }

[Java] 纯文本查看 复制代码
 public static String byte2hex(byte[] paramArrayOfByte)
  {
    String str1 = "";
    int i = 0;
    if (i >= paramArrayOfByte.length) {
      return str1.toUpperCase();
    }
    String str2 = Integer.toHexString(paramArrayOfByte[i] & 0xFF);
    if (str2.length() == 1) {}
    for (str1 = new StringBuffer().append(str1).append("0").toString() + str2;; str1 = str1 + str2)
    {
      i += 1;
      break;
    }
  }

给en加密函数传入的参数就是id值,该值范围由this.id = ((int)(Math.random() * 1000000000 % 100000)); 这里决定。

我使用java写了一个简单的获取激活码的代码,获取到一下激活码:
9e3bcb38bc593906eb7614756ef11907
61beeb148d50f2cb0151f7d04cbe6aa8
4b7cf14cca1cb8a8d4b3f65654126b75

部分关键代码:


7.png
上传了word的格式的

新建 Microsoft Word 文档.doc

286.81 KB, 下载次数: 85, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 18吾爱币 +27 热心值 +18 收起 理由
红色沂蒙 + 1 + 1 谢谢@Thanks!
神经病的精神病 + 1 + 1 我还是看不懂
wlpkcheng + 1 + 1 感谢补充,但是做为新手的我还是看不懂哈
baqzh + 1 + 1 用心讨论,共获提升!
bai123tt + 1 + 1 谢谢@Thanks!
sunnylds7 + 1 谢谢@Thanks!
qtfreet00 + 12 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
qaz003 + 1 谢谢@Thanks!
qaz6990300 + 1 + 1 用心讨论,共获提升!
zamliage + 1 + 1 热心!
ESRGA18 + 1 + 1 谢谢@Thanks!
lonznt + 1 + 1 谢谢@Thanks!
卡哇伊vs + 1 + 1 谢谢@Thanks!
碧海丹青 + 1 + 1 谢谢@Thanks!
52pojie3009 + 1 + 1 谢谢@Thanks!
dwq308 + 1 + 1 谢谢@Thanks!
连晋 + 1 + 1 点赞
七个八个九个 + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

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

 楼主| 小灰灰~ 发表于 2017-12-21 14:41
凉生我怕怕 发表于 2017-12-21 14:18
你少写了这个东西  也比较重要
  int j = paramString.length();
    if (j % 2 == 1) {

其实不用的,1 对应的注册码是80e1f490cc8e40d6adfbffa34555ec18,可以注册成功的
int j = paramString.length();
    if (j % 2 == 1) {
      return (byte[])null;
    }
是对密文的长度判断的
String[] arrayOfString = paramAnonymousView.split("z");
虽然判断了明文中是否包含z,但是包含也可以使用,只是不会提示:软件无限期使用
  String[] arrayOfString = paramAnonymousView.split("z");
        try
        {
          Integer.parseInt(arrayOfString[0], 16);
          Toast.makeText(FAppProtect.this, "启动成功,一起去浪吧,小伙子!", 2000).show();
          paramAnonymousView = "激活成功,不止心殇告诫大家:请尊重作者也尊重自己,不要非法转载别人,否则和谐没用了不要找我&#128545;";
          if (arrayOfString.length > 1) {
            paramAnonymousView = "软件无限期使用" + FAppProtect.formatDuring(Long.parseLong(arrayOfString[1]));
          }
连晋 发表于 2017-12-21 14:18
你少写了这个东西  也比较重要
  int j = paramString.length();
    if (j % 2 == 1) {
      return (byte[])null;
    }

加密之前的明文长度必须是2 的   倍数   

并且  必须包含 字符串z

String[] arrayOfString = paramAnonymousView.split("z");
连晋 发表于 2017-12-21 14:16
 楼主| 小灰灰~ 发表于 2017-12-21 14:20
凉生我怕怕 发表于 2017-12-21 14:16
哈哈 我还做了视频的 分析  分析wlpkcheng老铁的吃鸡辅助注册码算法

厉害了 老铁,我新手,第一次写,写的不好,得向你好好学习
连晋 发表于 2017-12-21 14:38
小灰灰~ 发表于 2017-12-21 14:20
厉害了 老铁,我新手,第一次写,写的不好,得向你好好学习

我也是新手 哈哈
 楼主| 小灰灰~ 发表于 2017-12-21 14:46

多多交流哈,向大佬学习,看你发帖子就能感觉出来你的功底很不错,比我厉害
kk1212 发表于 2017-12-21 15:11
我是过来跟着学习一下的,
连晋 发表于 2017-12-21 15:24
小灰灰~ 发表于 2017-12-21 14:41
其实不用的,1 对应的注册码是80e1f490cc8e40d6adfbffa34555ec18,可以注册成功的
int j = paramString. ...

split 是用z字符串来分割 返回数组  = = 哈哈  某种意义上面来说确实可以判断是否字符串包含z

= = 我说的就是判断密文的长度是否是2的倍数
hongxw 发表于 2017-12-21 15:43
有矛就有盾,有盾就有矛
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-5-5 12:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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