吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9276|回复: 21
收起左侧

[Android 原创] 注册算法简单分析(菜鸟级)

[复制链接]
lakshmi 发表于 2015-7-30 17:17
       最近正在学习android逆向分析,于是打算找个apk练练手,在咱论坛上看到 http://www.52pojie.cn/thread-191522-1-1.html 分析,但是元亨利之贞大大只是分析了修改程序流程来实现破解,我一咬牙一跺脚,打算来分析一下注册算法,于是就有了这篇混积分的帖子

     首先是安装软件测试测试,发现提示有更新,不更新还不让运行,找到代码如下,修改后重新编译运行,找到软件注册入口如下:


1.png
                                       


分析代码找到判断注册是否成功的地方
[AppleScript] 纯文本查看 复制代码
00000084  sget-object             v2, a->o:String #获取机器码
00000088  invoke-static           d->a(String, String)Z, v2, v0  #注册和比较算法
0000008E  move-result             v2
00000090  if-nez                  v2, :A6
:94
00000094  invoke-virtual          TextView->setTextColor(I)V, v1, v3
0000009A  const-string            v0, "您输入的注册码不对。"
0000009E  invoke-virtual          TextView->setText(CharSequence)V, v1, v0
000000A4  goto                    :7A
:A6
000000A6  const/high16            v2, 0xFFFFFFFFFFFF0000
000000AA  invoke-virtual          TextView->setTextColor(I)V, v1, v2
000000B0  const-string            v2, "注册成功,点击“退出”。"
000000B4  invoke-virtual          TextView->setText(CharSequence)V, v1, v2


可以发现重点在          d->a(String, String)Z, v2, v0 这个函数中,进去看看,代码如下:
[AppleScript] 纯文本查看 复制代码
.method public static a(String, String)Z
          .registers 5
00000000  const/4                 v0, 0x1
00000002  const/4                 v1, 0x0
00000004  sget-object             v2, d->a:b  
00000008  invoke-virtual          b->a(String)String, v2, p0  
0000000E  move-result-object      v2
00000010  invoke-static           d->a(String)String, v2
00000016  move-result-object      v2
00000018  sput-object             v2, a->p:String
0000001C  sget-object             v2, a->p:String
00000020  invoke-virtual          String->equals(Object)Z, v2, p1   #将计算结果和用户输入的注册码进行比较
00000026  move-result             v2
00000028  if-eqz                  v2, :32
:2C
0000002C  sput-boolean            v0, a->q:Z
:30
00000030  return                  v0
:32
00000032  sput-boolean            v1, a->q:Z
00000036  move                    v0, v1
00000038  goto                    :30
.end method


这个函数的功能是将机器码经过一系列计算,然后将计算结果和用户输入的代码进行比较,由此可以判断注册算法肯定在如下两个函数中:
[AppleScript] 纯文本查看 复制代码
invoke-virtual b->a(String)String, v2, p0 
[AppleScript] 纯文本查看 复制代码
00000010 invoke-static d->a(String)String, v2

首先看第一个函数:
[AppleScript] 纯文本查看 复制代码
.method public a(String)String
          .registers 5
00000000  invoke-direct           b->a()V, p0 #这个函数是初始化变量,0x67452301,0xEFCDAB89, 0x98BADCFE, 0x10325476  初步判断函数为MD5
00000006  invoke-virtual          String->getBytes()[B, p1
0000000C  move-result-object      v0
0000000E  invoke-virtual          String->length()I, p1
00000014  move-result             v1
00000016  invoke-direct           b->a([B, I)V, p0, v0, v1 #  将机器码和其长度传递给函数, 这个函数内部函数更加确定了这个函数是MD5算法函数
0000001C  invoke-direct           b->b()V, p0
00000022  const-string            v0, ""
00000026  iput-object             v0, p0, b->c:String
0000002A  const/4                 v0, 0x0
:2C
0000002C  const/16                v1, 0x10
00000030  if-lt                   v0, v1, :3A
:34
00000034  iget-object             v0, p0, b->c:String
00000038  return-object           v0
:3A
0000003A  iget-object             v1, p0, b->c:String
0000003E  new-instance            v2, StringBuilder
00000042  invoke-static           String->valueOf(Object)String, v1
00000048  move-result-object      v1
0000004A  invoke-direct           StringBuilder-><init>(String)V, v2, v1
00000050  iget-object             v1, p0, b->g:[B
00000054  aget-byte               v1, v1, v0
00000058  invoke-static           b->b(B)String, v1
0000005E  move-result-object      v1
00000060  invoke-virtual          StringBuilder->append(String)StringBuilder, v2, v1
00000066  move-result-object      v1
00000068  invoke-virtual          StringBuilder->toString()String, v1
0000006E  move-result-object      v1
00000070  iput-object             v1, p0, b->c:String
00000074  add-int/lit8            v0, v0, 0x1
00000078  goto                    :2C
.end method


因此知道这个函数是MD5算法函数,返回值为MD5的Hash结果,接着看下一个函数,函数参数是机器码的MD5值:
[AppleScript] 纯文本查看 复制代码
.method public static a(String)String
          .registers 10
00000000  const/4                 v8, 0x3
00000002  const/16                v7, 0xC
00000006  const/4                 v6, 0x7
00000008  const/4                 v2, 0x0
0000000A  const-string            v0, ""
0000000E  const-string            v3, ""
00000012  invoke-virtual          String->length()I, p0 #获取Hash值的长度
00000018  move-result             v1
0000001A  if-lez                  v1, :2C  #如果长度小于等于0 跳转
:1E
0000001E  move                    v1, v2
:20
00000020  invoke-virtual          String->length()I, p0 
00000026  move-result             v4
00000028  if-lt                   v1, v4, :EA  #判断是否读取到了最后一个字符(去除字母功能循环)
:2C 
0000002C  invoke-virtual          String->length()I, v0
00000032  move-result             v1
00000034  if-lt                   v1, v7, :6A  #如果长度小于12则跳转到6A

:38  #下面这段函数是将字符串的前六位和后六位交换位置
00000038  new-instance            v1, StringBuilder
0000003C  invoke-virtual          String->substring(I, I)String, v0, v6, v7  #取出字符串的7-12位
00000042  move-result-object      v4
00000044  invoke-static           String->valueOf(Object)String, v4
0000004A  move-result-object      v4
0000004C  invoke-direct           StringBuilder-><init>(String)V, v1, v4
00000052  invoke-virtual          String->substring(I, I)String, v0, v2, v6    #取出字符串的1-6位
00000058  move-result-object      v0
0000005A  invoke-virtual          StringBuilder->append(String)StringBuilder, v1, v0
00000060  move-result-object      v0
00000062  invoke-virtual          StringBuilder->toString()String, v0
00000068  move-result-object      v0
:6A
0000006A  move-object             v1, v3
0000006C  move                    v3, v2
:6E
0000006E  invoke-virtual          String->length()I, v0
00000074  move-result             v4
00000076  if-lt                   v3, v4, :128
:7A
0000007A  invoke-virtual          String->length()I, v1
00000080  move-result             v0
00000082  const/16                v3, 0xB 
00000086  if-gt                   v0, v3, :A6    #如果字符串长度大于12则跳转到A6
:8A
0000008A  invoke-static           Long->parseLong(String)J, v1  #当字符串长度小于等于12时,将其转换成长整型
00000090  move-result-wide        v0
00000092  const-wide              v3, 0x1CBE991A14      
0000009C  add-long/2addr          v0, v3   #将其与数字123456789012 相加
0000009E  invoke-static           String->valueOf(J)String, v0, v1
000000A4  move-result-object      v1   #将结果转换成字符串
:A6
000000A6  new-instance            v0, StringBuilder
000000AA  invoke-virtual          String->substring(I, I)String, v1, v6, v7  #取出字符串的7-12位
000000B0  move-result-object      v3
000000B2  invoke-static           String->valueOf(Object)String, v3
000000B8  move-result-object      v3
000000BA  invoke-direct           StringBuilder-><init>(String)V, v0, v3    
000000C0  invoke-virtual          String->substring(I, I)String, v1, v2, v8   #取出字符串的1-3位
000000C6  move-result-object      v2
000000C8  invoke-virtual          StringBuilder->append(String)StringBuilder, v0, v2
000000CE  move-result-object      v0
000000D0  invoke-virtual          String->substring(I, I)String, v1, v8, v6  #取出字符串的4-6位
000000D6  move-result-object      v1
000000D8  invoke-virtual          StringBuilder->append(String)StringBuilder, v0, v1
000000DE  move-result-object      v0
000000E0  invoke-virtual          StringBuilder->toString()String, v0
000000E6  move-result-object      v0
000000E8  return-object           v0      #将转换后的结果返回,成真正的验证码
:EA
000000EA  invoke-virtual          String->charAt(I)C, p0, v1 #取出字符
000000F0  move-result             v4
000000F2  invoke-static           Character->isDigit(C)Z, v4 #判断该字符是否是数字
000000F8  move-result             v5
000000FA  if-eqz                  v5, :120     # 如果取出的是字符就跳转到120
:FE
000000FE  new-instance            v5, StringBuilder   #取出的是数字这将其添加到字符串V5的的末尾
00000102  invoke-static           String->valueOf(Object)String, v0
00000108  move-result-object      v0
0000010A  invoke-direct           StringBuilder-><init>(String)V, v5, v0
00000110  invoke-virtual          StringBuilder->append(C)StringBuilder, v5, v4
00000116  move-result-object      v0
00000118  invoke-virtual          StringBuilder->toString()String, v0
0000011E  move-result-object      v0
:120
00000120  add-int/lit8            v1, v1, 0x1
00000124  goto/16                 :20
:128
00000128  add-int/lit8            v4, v3, 0x1              # v4=v3+1
0000012C  invoke-virtual          String->substring(I, I)String, v0, v3, v4   #依次取出字符
00000132  move-result-object      v4
00000134  invoke-static           Integer->parseInt(String)I, v4  #将字符转换成数字
0000013A  move-result             v4
0000013C  xor-int/lit8            v4, v4, 0x5   # 将数字进行5次方
00000140  new-instance            v5, StringBuilder
00000144  invoke-static           String->valueOf(Object)String, v1 
0000014A  move-result-object      v1
0000014C  invoke-direct           StringBuilder-><init>(String)V, v5, v1
00000152  invoke-static           String->valueOf(I)String, v4     #将数字转换成字符串
00000158  move-result-object      v1
0000015A  invoke-virtual          StringBuilder->append(String)StringBuilder, v5, v1   #将字符串添加到字符串V1的末尾
00000160  move-result-object      v1
00000162  invoke-virtual          StringBuilder->toString()String, v1
00000168  move-result-object      v1
0000016A  add-int/lit8            v3, v3, 0x1   #V3 = V3+1
0000016E  goto                    :6E
.end method

从方法中分析出注册算法的流程如下:
[AppleScript] 纯文本查看 复制代码
Step0: 初始化字符串R1,2,3,4,5为空 (其中R1,2,3,4为中间变量保存值,R5为计算结果)。
Step1: 计算机器码的MD5值 结果为R1;
Step2: 去掉R1中的所有字母结果为R2;
Step3: 如果R2的长度不大于12则将R2的值赋给R3,然后跳转到Step5;
Step4: 去除R2的前12位并将前六位和后六位交换位置,结果赋值给R3;
Step5: 依次将R3中的每一位转换成数值,并进行5次方,然后转换成字符串,粘贴在字符串R4的末尾;
Step6: 如果R4的长度大于11位则跳转到Step8;
Step7: 将R4转换成长整型然后和123456789012相加,结果保存在R4中;
Step8: 依次取出R4的7到12位,1-3位,4-6位粘贴到R5的末尾,R5即为真正注册码。

到此算法分析完成。接下来是编写注册机,python代码如下:
[Python] 纯文本查看 复制代码
#!/usr/bin/env python
#coding=utf-8

import hashlib, getopt, sys, os

def  usage(self):
    print("[+] usage: python registcode.py -c DA44015E-2414")
def registCode(hashcode):
    len1 = 3;
    len2 = 12;
    len3 = 7;
    tempcode = ""
    result = ""
    if len(hashcode) > 0:
        for temp in hashcode:
            if temp.isdigit():
                tempcode += temp
    if len(tempcode) > len2:
        tempcode = tempcode[len3:len2] + tempcode[:len3]
    for temp in tempcode:
        result += str(int(temp)^5)
    if len(result) <12:
        result = str(int(result) +123456789012)
    
    return result[len3:len2] + result[:len1] + result[len1:len3]   

               
if __name__ == '__main__':
    opts, args = getopt.getopt(sys.argv[1:], "hc:");
    machinecode = ""
    for op,value in opts:
        if op == "-c":
            machinecode = value
        elif op == "-h":
            usage()
            sys.exit()
        
    if len(machinecode) == 0:
        print("[-] No Machine Code")
        sys.exit()
    print("[+] machine code: %s"%machinecode)
    md = hashlib.md5();
    md.update(machinecode.encode(encoding='gb2312'))
              
    print(md.hexdigest())
    print(registCode(md.hexdigest()))

运行结果如下:
[Asm] 纯文本查看 复制代码
[+] machine code: DA44015E-2414

[+] MD5 code: 227c1bab3334277b3e8c06ca227b4a20

[+] regist code: 246661722677


注册成功.png

打完收工,附上JAVA和Python实现的简单注册代码,菜鸟一枚,大牛勿喷。
注册.png

注册.zip

1.8 KB, 下载次数: 10, 下载积分: 吾爱币 -1 CB

注册算法实现文件

免费评分

参与人数 3威望 +1 热心值 +3 收起 理由
低调(d-iao) + 1 已答复!
diaojianxiao + 1 谢谢@Thanks!
qtfreet00 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.

查看全部评分

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

Hmily 发表于 2015-8-6 11:25
lakshmi 发表于 2015-8-6 08:37
感谢H大, 排版的时候我是将图片拖上去的,最后发现图片显示不出来,所以就直接将图片当成附 ...

图片上传后,在正文中点击下你上传的图片就直接贴进去了,不用脱。。。。你可以试试
 楼主| lakshmi 发表于 2015-8-6 08:37
Hmily 发表于 2015-8-5 18:51
图片贴的有问题?我重新编辑下,楼主看看对不对?

感谢H大, 排版的时候我是将图片拖上去的,最后发现图片显示不出来,所以就直接将图片当成附件传上去了。

点评

图片上传后,在正文中点击下你上传的图片就直接贴进去了,不用脱。。。。你可以试试  详情 回复 发表于 2015-8-6 11:25
飞火 发表于 2015-7-30 17:23
wakichie 发表于 2015-7-30 17:27
还是看不懂啊
 楼主| lakshmi 发表于 2015-7-30 17:32

额,只能表示我的表述能力还存在问题,初次写,本来分析成JAVA代码流程就会很清晰,但是为了熟悉Smail语言,就硬着头皮分析了一下
lixinmingo 发表于 2015-7-30 17:38
牛,学习学习!
syrmb 发表于 2015-7-30 18:22
敢不敢来个脱壳的 现在大部分apk都加固了
 楼主| lakshmi 发表于 2015-7-30 20:05
syrmb 发表于 2015-7-30 18:22
敢不敢来个脱壳的 现在大部分apk都加固了

新手,见谅见谅,以后会有的
diaojianxiao 发表于 2015-7-30 20:59
感谢分享
Mouette 发表于 2015-7-30 22:50 来自手机
楼主是新手,我差点就信了,哈哈
Ericky 发表于 2015-7-30 23:06
坚持就会有收货的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 17:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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