吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 25593|回复: 51
收起左侧

[Android 原创] Keygen Challenge

  [复制链接]
h_one 发表于 2014-6-7 16:29
本帖最后由 zxcfvasd 于 2014-6-7 16:29 编辑

【标题】: Keygen Challenge 攻略
【作者】: h_one

也有段时间没有发帖子了,前两天找到Claud大侠推荐的一个android cm,IDA,">A Keygen Challenge for Android  初学android的菜菜也来练练手,今天将自己分析的过程与大家分享下。

这个游戏共有5关:
1.jpg

一.程序流程分析
使用APK改之理反编译 通过AndroidManfest.xml找到入口Activity的smali进行分析。找到oncreate创建下拉列表,共5个选项,并为每个选项绑定一个值,依次是1~5 分别表示难易程度
[AppleScript] 纯文本查看 复制代码
#levels
    const v6, 0x1090008
 
    invoke-static {p0, v5, v6}, Landroid/widget/ArrayAdapter;->createFromResource(Landroid/content/Context;II)Landroid/widget/ArrayAdapter;
#ArrayAdapter adapter = ArrayAdapter.createFromResource(R.id.levels, v6);
    move-result-object v0
 
    .line 64
    .local v0, "adapter":Landroid/widget/ArrayAdapter;, "Landroid/widget/ArrayAdapter<Ljava/lang/CharSequence;>;"
    const v5, 0x1090009
 
    invoke-virtual {v0, v5}, Landroid/widget/ArrayAdapter;->setDropDownViewResource(I)V
 
    .line 65
    iget-object v5, p0, Lcom/me/keygen/activity/MainActivity;->levelSelect:Landroid/widget/Spinner;
#adapter.setDropDownViewResource(v5);
    invoke-virtual {v5, p0}, Landroid/widget/Spinner;->setOnItemSelectedListener(Landroid/widget/AdapterView$OnItemSelectedListener;)V
 
    .line 67
    iget-object v5, p0, Lcom/me/keygen/activity/MainActivity;->levelSelect:Landroid/widget/Spinner;
#创建下拉列表框, 并且位每一个选项绑定一个值
    invoke-virtual {v5, v0}, Landroid/widget/Spinner;->setAdapter(Landroid/widget/SpinnerAdapter;)V
 
    .line 69
    iget-object v5, p0, Lcom/me/keygen/activity/MainActivity;->submit:Landroid/widget/Button;
 
    new-instance v6, Lcom/me/keygen/activity/MainActivity$1;
 
    invoke-direct {v6, p0}, Lcom/me/keygen/activity/MainActivity$1;-><init>(Lcom/me/keygen/activity/MainActivity;)V
 
    invoke-virtual {v5, v6}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
#创建 注册按钮监听事件
    .line 77

进入按钮事件后调用validateSerial() 函数,获取用户名和序列号,然后根据选择的currentChallenge字段来进入不同难度,默认值是1,最后调用接口函数isValid对用户名序列号验证
[AppleScript] 纯文本查看 复制代码
.line 102
    iget-object v0, p0, Lcom/me/keygen/activity/MainActivity;->name:Landroid/widget/EditText;
 
    invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
 
    move-result-object v0
 
    invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;
 
    move-result-object v7
#String name = this.name.getText().toString();
    .line 103
    .local v7, "name":Ljava/lang/String;
    iget-object v0, p0, Lcom/me/keygen/activity/MainActivity;->serial:Landroid/widget/EditText;
 
    invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
 
    move-result-object v0
 
    invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;
 
    move-result-object v8
#String serial = this.serial.getText().toString();
    .line 104
    .local v8, "serial":Ljava/lang/String;
    iget v0, p0, Lcom/me/keygen/activity/MainActivity;->currentChallenge:I
#currentChallenge 字段 是根据下拉列表选择的按钮,也就是难易程序的选择
    invoke-direct {p0, v0}, Lcom/me/keygen/activity/MainActivity;->getVerifierForChallenge(I)Lcom/me/keygen/verifiers/KeyVerifier;
 
    move-result-object v6
#KeyVerifier kv = getVerifierForChallenge(this.currentChallenge);  
    .line 105
    .local v6, "kv":Lcom/me/keygen/verifiers/KeyVerifier;
    if-nez v6, :cond_0
 
    .line 107
    const-string v0, "No Verifier Present For This Level"
 
    invoke-static {p0, v0, v10}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
    move-result-object v0
 
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V
 
    .line 129
    :goto_0
    return-void
 
    .line 110
    :cond_0
    invoke-interface {v6, v7, v8}, Lcom/me/keygen/verifiers/KeyVerifier;->isValid(Ljava/lang/String;Ljava/lang/String;)Z
#kv.isValid()   调用KeyVerifier接口的isValid对用户名序列号验证
    move-result v9


二.闯关
0x1
第一关很简单,直接看源码,写出注册机搞定
2.png

抠出代码写注册机. 我用的C
[C] 纯文本查看 复制代码
int main(int argc, char* argv[])
{
    char username[20] = {0};
    printf("input username:");
    scanf("%s", username);
 
    int i = 0, m = 0;
    int len = strlen(username);
    for (int j = 0; j < len; j++)
    {
        m = username[j];
        i = m ^ i + m * m;
    }
    printf("%d\n", i);
    getchar();
}



0x2
第二关也比较简单,需要源码与smlia结合看

3.png


上图就是算法,首先用户名大于4位,将输入用户名转化成大写,依次取每一位变换求和得到 l , 将求和值转化成字符串str2。这里反编译出现了不可见的字符,对比查看smali,一个是0x30,一个是0x40,相差0x10。j是str2每一位加0x30求和值,因此输入的序列号如果与str2长度相同的话只需要每一位比str都大0x10,这样就可以找到序列号。
根据以上分析写出注册机:
[C] 纯文本查看 复制代码
int main(int argc, char* argv[])
{
    char username[20] = {0};
    printf("input username:");
    scanf("%s", username);
 
     
/************************************************************************/
/*                     challeng1                                        */
/************************************************************************/
/*  int i = 0, m = 0;
    int len = strlen(username);
    for (int j = 0; j < len; j++)
    {
        m = username[j];
        i = m ^ i + m * m;
    }
    printf("%d\n", i);
    getchar();*/
 
 
 
/************************************************************************/
/*                    challeng2                                         */
/************************************************************************/
    int name_len = 0,i = 0;
    name_len = strlen(username);
    char str1[20] = {0};
    long nameSum = 0;
    for (i = 0; i < name_len; i++)
    {
        if (username[i] >= 'a' && username <= 'z')[/i]
   {
            username -= 32;
        }
    }
    for (i = 0; i < name_len; i++)
    {
        nameSum = 3 * (nameSum + username) - 64;
    }

 itoa(nameSum, str1, 10);
    char *finalsum = new char[strlen(str1)];
    for (i = 0; i < strlen(str1); i++)
    {
        finalsum = str1 + 16;
    }
    printf("%s\n", finalsum);
    return 0;
[i]}



0x3
这个比前两个稍微难了些,但也只是java层面的。编译为源码后只能看到一部分java代码了,关键的isVaild函数做了处理,只有老老实实的看smali了.
4.png

检查Serial字符串格式
[Java] 纯文本查看 复制代码
string[] parts = serial.split("-");
if(parts.length != 0x8)
    return; 


说明序列号格式是 XXXXX-XXXX-XXXXX-XXXXXX-XXXX-XXXX-XXXX-XXXX形式的
[AppleScript] 纯文本查看 复制代码
.line 25
    const-string v9, "-"
 
invoke-virtual {p2, v9}, Ljava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String;
 
    move-result-object v5
#String[] parts = serial.split("-");
    .line 26
    .local v5, "parts":[Ljava/lang/String;
    array-length v9, v5
 
    const/16 v10, 0x8
 
    if-eq v9, v10, :cond_1
#if(parts.length != 0x8); return ;
    .line 92
    :cond_0
    :goto_0
    return v8
 
    .line 31
    :cond_1


这是一个for循环 ,8段字符串正则匹配,由const-string v10, "[0-9A-F][0-9A-F][0-9A-F][0-9A-F]" 可以知道每段4个字符且每个字符为0~9 A~F
serial:xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx(0~9||A~F)
[AppleScript] 纯文本查看 复制代码
 :cond_1
    const/4 v7, 0x0
#int x = 0;
    .local v7, "x":I
    :goto_1
    array-length v9, v5
#v9 = parts.length;
    if-ge v7, v9, :cond_2
#if(v7 >= 0x8)
    .line 33
    aget-object v9, v5, v7
 
    const-string v10, "[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
 
    invoke-virtual {v9, v10}, Ljava/lang/String;->matches(Ljava/lang/String;)Z
#每段字符串正则匹配    
    move-result v9
 
    if-eqz v9, :cond_0
 
    .line 31
    add-int/lit8 v7, v7, 0x1
 
    goto :goto_1


接下来是两个for循环,将secretBytes 数据写入输出流

[Java] 纯文本查看 复制代码
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(0x31);
for(int i = 0; i < secretBytes.length; i+=2) 
{ 
   baos.write(secretBytes); 
   baos.write(i+1); 
} 
for(int i = 1; i < secretBytes.length; i += 2) 
{ 
   baos.write(secretByte); 
   baos.write(i+1); 
}



[AppleScript] 纯文本查看 复制代码
 .line 39
    :cond_2
    new-instance v0, Ljava/io/ByteArrayOutputStream;
#ByteArrayOutputStream baos = new ByteArrayOutputStream();
    invoke-direct {v0}, Ljava/io/ByteArrayOutputStream;-><init>()V
 
    .line 41
    .local v0, "baos":Ljava/io/ByteArrayOutputStream;
    const/16 v9, 0x31
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(0x31);
    .line 43
    const/4 v7, 0x0
#int i = 0;
    :goto_2
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->secretBytes:[B
 
    array-length v9, v9
 
    if-ge v7, v9, :cond_3
# i < secretBytes.length;
    .line 45
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->secretBytes:[B
 
    aget-byte v9, v9, v7
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(secretBytes);
    .line 46
    add-int/lit8 v9, v7, 0x1
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(i+1);
    .line 43
    add-int/lit8 v7, v7, 0x2
#i+=2;
    goto :goto_2
 
    .line 49
    :cond_3
    const/4 v7, 0x1
##int v7 = 1;
    :goto_3
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->secretBytes:[B
 
    array-length v9, v9
 
    if-ge v7, v9, :cond_4
# v7 > secretBytes.length;
    .line 51
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->secretBytes:[B
 
    aget-byte v9, v9, v7
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(secretByte);
    .line 52
    add-int/lit8 v9, v7, 0x1
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(i+1);
    .line 49
    add-int/lit8 v7, v7, 0x2
 
    goto :goto_3
接下来一个for循环是将序列号的前4段部分 经处理依次写入标准输出流

[Java] 纯文本查看 复制代码
baos.write(0x30);
baos.write(0x30);
for(int = 0; i < parts.length/2; i++)
{
    baos.write(parts.Charset.forName("US_ASCII"));
  baos.wirte("-");
}
baos.write(secretBytes);


[AppleScript] 纯文本查看 复制代码
 .line 55
    :cond_4
    invoke-virtual {v0, v11}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(0x30);
    .line 56
    invoke-virtual {v0, v11}, Ljava/io/ByteArrayOutputStream;->write(I)V
#baos.write(0x30);
    .line 58
    const/4 v7, 0x0
#i = 0;
    :goto_4
    array-length v9, v5 #v5存放是注册码数组(parts)
#0x8 = parts.length
    div-int/lit8 v9, v9, 0x2
#v9 = 4; 获取序列号的前四段
    if-ge v7, v9, :cond_5
#i < 4
    .line 62
    :try_start_0
    aget-object v9, v5, v7
#parts
    const-string v10, "US_ASCII"
 
    invoke-static {v10}, Ljava/nio/charset/Charset;->forName(Ljava/lang/String;)Ljava/nio/charset/Charset;
 
    move-result-object v10
 
    invoke-virtual {v9, v10}, Ljava/lang/String;->getBytes(Ljava/nio/charset/Charset;)[B
 
    move-result-object v9
 
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write([B)V
#baos.write(parts.Charset.forName("US_ASCII"));
    .line 63
    const/16 v9, 0x2d
#紧接着写入“-”
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write(I)V
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
 
    .line 58
    add-int/lit8 v7, v7, 0x1
#i++;
    goto :goto_4
 
    .line 64
    :catch_0
    move-exception v1
 
    .local v1, "e":Ljava/lang/Exception;
    goto :goto_0
 
    .line 68
    .end local v1    # "e":Ljava/lang/Exception;
    :cond_5
    :try_start_1
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->secretBytes:[B
#baos.write(secretBytes);
    invoke-virtual {v0, v9}, Ljava/io/ByteArrayOutputStream;->write([B)V
    :try_end_1
    .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_1


接下来将前面准备的标准输出流数据经行MD5摘要,最后经过MD5处理后得到的32位字符串会保存在v2寄存器上,此处我们可以smali注入查看

[Java] 纯文本查看 复制代码
byte[] result = new byte[0x20];[/color]
[color=#000000]MessageDigest md = MessageDigest.getInstance("MD5");[/color]
[color=#000000]md.update(baos.toByteArray());[/color]
[color=#000000]result = md.digest();[/color]
[color=#000000]String sFinalKey = bytesToHex(md.digest()).toUpperCase();


[AppleScript] 纯文本查看 复制代码
.line 72
    const/16 v9, 0x20
 
    new-array v6, v9, [B
#byte[] result = new byte[0x20];
    .line 75
    .local v6, "result":[B
    :try_start_2
    const-string v9, "MD5"
 
    invoke-static {v9}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;
 
    move-result-object v4
#MessageDigest md = MessageDigest.getInstance("MD5");
    .line 76
    .local v4, "md":Ljava/security/MessageDigest;
    invoke-virtual {v0}, Ljava/io/ByteArrayOutputStream;->toByteArray()[B
 
    move-result-object v9
 
    invoke-virtual {v4, v9}, Ljava/security/MessageDigest;->update([B)V
#md.update(baos.toByteArray());
    .line 77
    invoke-virtual {v4}, Ljava/security/MessageDigest;->digest()[B
    :try_end_2
    .catch Ljava/lang/Exception; {:try_start_2 .. :try_end_2} :catch_2
 
    move-result-object v6
#result = md.digest();
    .line 80
    invoke-static {v6}, Lcom/me/keygen/verifiers/challenge/Challenge3Verifier;->bytesToHex([B)Ljava/lang/String;
 
    move-result-object v9
 
    invoke-virtual {v9}, Ljava/lang/String;->toUpperCase()Ljava/lang/String;
#String sFinalKey = bytesToHex(md.digest()).toUpperCase();
    move-result-object v2[/color][color=#0000ff]   #此处的v2就是最终MD5处理后的字符串,在这里我们可以进行Smila注入,查看v2值[/color][color=#000000]



将前面得到的MD5字符串,取偶数位,依次和输入序列号的后16位比较。因此我们可以在前面经行Smali注入,取出偶数位则是正确序列号
[AppleScript] 纯文本查看 复制代码
.line 81
    .local v2, "foo":Ljava/lang/String;
    invoke-virtual {p2}, Ljava/lang/String;->length()I
 
    move-result v9
 
  div-int/lit8 v9, v9, 0x2
#v9 = serial.length/2
    invoke-virtual {p2, v9}, Ljava/lang/String;->substring(I)Ljava/lang/String;
 
    move-result-object v3
#lastHalf = serial.substring(serial.length/2); 取输入序列号后半部分
    .line 82
    .local v3, "lastHalf":Ljava/lang/String;
    const-string v9, "-"
 
    const-string v10, ""
 
    invoke-virtual {v3, v9, v10}, Ljava/lang/String;->replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
#lastHalf.replaceAll("-", ""); 去除后半部分序列号中的“-”
    move-result-object v3
 
    .line 84
    const/4 v7, 0x0
#int i = 0;
    :goto_5
    invoke-virtual {v2}, Ljava/lang/String;->length()I
 
    move-result v9
 
    if-ge v7, v9, :cond_6
#i < sFinalString.length();
    .line 86
    invoke-virtual {v2, v7}, Ljava/lang/String;->charAt(I)C
 
    move-result v9
#v9 = sFinalString.charAt(i);

    div-int/lit8 v10, v7, 0x2
#v10 = i/2;
    invoke-virtual {v3, v10}, Ljava/lang/String;->charAt(I)C
#v10 = lastHalf.charAt(v10);
    move-result v10
 
    if-ne v9, v10, :cond_0 
    #关键比较,将serial前半部分处理后的数据,与后半部分比较
    #sFinalString是经过MD5处理后32的字符串, lastHalf是序列号后半部分且去除“-”的字符串
    #sFinalString[i*2] cmp lastHalf
    .line 84
    add-int/lit8 v7, v7, 0x2
#i += 2;
    goto :goto_5
 
    .line 69
    .end local v2    # "foo":Ljava/lang/String;
    .end local v3    # "lastHalf":Ljava/lang/String;
    .end local v4    # "md":Ljava/security/MessageDigest;
    .end local v6    # "result":[B
    :catch_1
    move-exception v1
 
    .restart local v1    # "e":Ljava/lang/Exception;
    goto/16 :goto_0
 
    .line 78
    .end local v1    # "e":Ljava/lang/Exception;
    .restart local v6    # "result":[B
    :catch_2
    move-exception v1
 
    .restart local v1    # "e":Ljava/lang/Exception;
    goto/16 :goto_0

算法到此结束可以发现整个过程与用户名毫无关系。
smlia 注入
java代码:
log.v("H_ONE3", v2);

smlia代码:  
const-string v12, "H_ONE3"
invoke-static{v12, v2}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I

输入序列号1111-1111-1111-1111-2222-2222-2222-2222,然后logcat 查看.
5.png
序列号为1111-1111-1111-1111-890D-0171-0C54-E3A1 通关!


0x4
这个也是java层代码,且没有任何混淆和反调试,可以直接得到源码

6.png

发现又是一大坨算法. 这些都是浮云. 注意上面圈出的
localBigInteger1是经过一些列的算法处理paramString1后得到的结果,localBigInteger2是序列号字符串转化成BigInteger类型数据
boolean bool = localBigInteger1.xor(localBigInteger2).equals(new BigInteger("0"));一句可以说明localBigInteger1就是正确的序列号。啥也不说了,直接注入干掉。

对应的smali代码以及注入
[AppleScript] 纯文本查看 复制代码
.line 62
    .local v5, "serialInt":Ljava/math/BigInteger;
    sget-object v7, Ljava/lang/System;->out:Ljava/io/PrintStream;
#BigInteger serialInt = new BigInteger(serial);
    invoke-virtual {v2}, Ljava/math/BigInteger;->toString()Ljava/lang/String;
#bigOne.toString();
    move-result-object v8 #key
 
     
#此处smlia注入
    const-string v10, "H_ONE4"
    invoke-static{v10, v8},  Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
     
    invoke-virtual {v7, v8}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
#PrintStream.println(bigOne.toString);
    .line 63
    invoke-virtual {v2, v5}, Ljava/math/BigInteger;->xor(Ljava/math/BigInteger;)Ljava/math/BigInteger;
#bigOne.xor(serialInt)
    move-result-object v7
#v7 = bigOne.xor(serialInt)
    new-instance v8, Ljava/math/BigInteger;
     
    const-string v9, "0"
 
    invoke-direct {v8, v9}, Ljava/math/BigInteger;-><init>(Ljava/lang/String;)V
#BigInteger v8 = new BigInteger("0"); v8也就是数字0
    invoke-virtual {v7, v8}, Ljava/math/BigInteger;->equals(Ljava/lang/Object;)Z
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
#BigOne xor serialInt等于0  说明BigOne 等于 serialInt  而serialInt就是输入的字符串
#所以此处可smila注入
    move-result v7
 
    .line 64
    .end local v5    # "serialInt":Ljava/math/BigInteger;
    :goto_2
    return v7

eg:
用户名:h_one
序列号: 94449870367585271808
7.png


0x5
第5关同样只有是java层代码,同样可以编译出源码,但是编译出的源码有时流程会出问题,说以关键地放最好还是对比smali看
比如:
8.png

上面圈出地方,编译的源码对比smali看可以发现出错了

第五关也就从这里分析起走。设备ID作为Challeng5Verifier参数传入,并由id变量保存,接下来分析接口函数isValid分析
9.png
好吧又可以直接注入上面Long.toString(l); 则是对应的正确序列号
对应smlia以及注入
[AppleScript] 纯文本查看 复制代码
   .line 52
    .end local v8    # "y":I
    :cond_2
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->matrix:[[I
 
    invoke-direct {p0, v9}, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->normalizeMatrix([[I)V
 
    .line 53
    iget-object v9, p0, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->matrix:[[I
 
    invoke-direct {p0, v9}, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->mst([[I)J
 
    move-result-wide v5
#long val = mst(this.matrix);   这个就是经过用户名处理后得到的正常序列号
 
    .line 54
    .local v5, "val":J
    sget-object v9, Ljava/lang/System;->out:Ljava/io/PrintStream;
 
    invoke-virtual {v9, v5, v6}, Ljava/io/PrintStream;->println(J)V
 
    .line 55
    invoke-direct {p0, p1, p2}, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->makeKey(Ljava/lang/String;Ljava/lang/String;)[B
 
    move-result-object v3
#byte[] input = makeKey(name, serial);
    .line 56
    .local v3, "input":[B
    invoke-static {v5, v6}, Ljava/lang/Long;->toString(J)Ljava/lang/String;
 
    move-result-object v9
# 这里经行注入
    const-string v11, "H_ONE5"
    invoke-static{v11, v9}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
     
    invoke-direct {p0, p1, v9}, Lcom/me/keygen/verifiers/challenge/Challenge5Verifier;->makeKey(Ljava/lang/String;Ljava/lang/String;)[B
 
    move-result-object v2

eg:
用户名:h_one
10.png

三.总结:个人觉得andoird程序若只是在java层面编写的,对于一个crack来说相当好搞。核心代码以及反调试最好用c/c++编写,NDK编译.so链接库。



点评

佩服~~~~~~~~~~  发表于 2017-5-2 21:37

免费评分

参与人数 3热心值 +3 收起 理由
zy2pj + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
zc123 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
你与明日 + 1 一个不错的东西!收藏了

查看全部评分

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

 楼主| h_one 发表于 2014-6-13 16:52
zc123 发表于 2014-6-11 19:29
请问2楼的附件是未修改的吗

对,没有修改过的.
zaq4736 发表于 2014-6-13 12:57
小野 发表于 2014-6-12 17:58
头像被屏蔽
刘宏伟大人丶 发表于 2014-6-12 17:17
给跪了 - - 膜拜大神
 楼主| h_one 发表于 2014-6-7 16:33
附件上传

com.me.keygen.activity.zip

19.39 KB, 下载次数: 33, 下载积分: 吾爱币 -1 CB

羅少 发表于 2014-6-7 17:01
@Hmily   必须加精!!!

点评

这个@小试锋芒 版主吧。  详情 回复 发表于 2014-6-7 17:39
ii丶BigBreast 发表于 2014-6-7 17:01
板凳,围观大牛
Hmily 发表于 2014-6-7 17:39
羅少 发表于 2014-6-7 17:01
@Hmily   必须加精!!!

这个@小试锋芒 版主吧。
闹够了没有 发表于 2014-6-7 18:00
膜拜大大
 楼主| h_one 发表于 2014-6-7 22:39
羅少 发表于 2014-6-7 17:01
@Hmily   必须加精!!!

哈哈哈,,,
 楼主| h_one 发表于 2014-6-7 22:41

这个cm游戏挺不错的.
D13 发表于 2014-6-9 20:34
围观大大。。
JoyChou 发表于 2014-6-9 22:58
哈哈。应该给个pediy链接
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 13:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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