Android Crackme分析
来源:互联网 发布:json解析技术有哪些 编辑:程序博客网 时间:2024/06/06 02:13
1.Crackme01
用APKtools反编译成smali代码 定位到关键部位如下:
invoke-static {v1}, Lcom/google/youngandroid/runtime;->sanitizeComponentData(Ljava/lang/Object;)Ljava/lang/Object; move-result-object v1 sget-object v2, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit35:Lgnu/math/IntNum; #V2=0x2E812 invoke-static {v1, v2}, Lgnu/lists/LList;->list2(Ljava/lang/Object;Ljava/lang/Object;)Lgnu/lists/Pair; move-result-object v1sget-object v2, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit36:Lgnu/lists/PairWithPosition; const-string v3, ">" invoke-static {v0, v1, v2, v3}, Lcom/google/youngandroid/runtime;->callYailPrimitive(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; move-result-object v0 sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; #v1=false if-eq v0, v1, :cond_0 #v0=v1 Ôòʧ°Ü Sv0ҪΪÕæ sget-object v0, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit0:Lgnu/mapping/SimpleSymbol; invoke-static {v0}, Lcom/google/youngandroid/runtime;->lookupInCurrentFormEnvironment(Lgnu/mapping/Symbol;)Ljava/lang/Object; move-result-object v0 sget-object v1, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit13:Lgnu/mapping/SimpleSymbol; const-string v2, "Crackme01! << by deurus >> - Good boy!"
如果是爆破的话,把False改成true即可。而我想的是分析下这个cm的算法,于是开始向上走起了。因为v1是False,所以v0要为True。
V0-->从callYailPrimitive(,,,)返回过来的,找到这函数:
.method public static callYailPrimitive(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; .locals 3 .parameter "prim" 对应V0 为函数返回值 .parameter "arglist" 对应V1 .parameter "typelist" 对应V2 Lit36.parameter "codeblocks$Mnname" 对应V3 = “>”
因此另外几个参数也要知晓才好分析,于是继续往上看 v3= ‘>’,然后又继续往上看,V2的值是Lit36。V1的值是list2函数返回的。继续追list2函数:
public static Pair list2(Object arg1, Object arg2) { return new Pair(arg1, new Pair(arg2, LList.Empty));}只是创建了两个Pair类 ,继续向上分invoke-static {v0, v1, v5, v2}, Lgnu/lists/PairWithPosition;->make(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;I)Lgnu/lists/PairWithPosition; move-result-object v0 sput-object v0, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit36:Lgnu/lists/PairWithPosition; const v0, 0x2e812 invoke-static {v0}, Lgnu/math/IntNum;->make(I)Lgnu/math/IntNum; move-result-object v0 sput-object v0, Lappinventor/ai_garikoitzmartinez/crackme01/Screen1;->Lit35:Lgnu/math/IntNum;析:
可以找到V1为1个装有2个成员的List,一个为用户自己输入的。一个就是Lit35=0x2E812。
而V2是多少,通过上述的代码赋给Lit36的值 以及callYailPrimitive函数中参数的定义,我想应该就是2个int类型了。
再把这部分分析结果拿出来看一下:
.locals 3 .parameter "prim" 对应V0 为函数返回值 也是关键点 .parameter "arglist" 2个参数 一个用户输入的 一个为0x2e812 .parameter "typelist" int int.parameter "codeblocks$Mnname" 对应V3 = “>”
不妨大胆猜想一下,应该就是这2个数比大小吧。于是进去callYailPrimitive函数中分析了下,确实如此:
2.Crackme02
如果是爆破的话还是只要改一个地方:
sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
if-eq v0, v1, :cond_2
把FALSE 改成 TRUE 即可。注册成功背景为绿色:
还是老套路,安好程序看一看先,看是个什么情况。发现了输入name和序列号是不正确的情况下,背景会显示为红色。然后用神器反编译好smali,我们去看代码,看看有什么我们的新发现!
分析了一会smali之后,发现还是看着蛋疼,看看源码吧:
public Object Button1_check$Click() { O后面还有2个给大家玩吧~累 休息总的来说主要提高了对smali代码的熟练度~收获还不错,纠正了一些理解上的偏差和巩固了之前的smali。(*^__^*) BY Ericky 2014.12.6bject v0; String v7 = "+"; String v5 = ""; runtime.addToCurrentFormEnvironment(Screen1.Lit12, Screen1.Lit28); runtime.addToCurrentFormEnvironment(Screen1.Lit14, Screen1.Lit11); if(runtime.isYailEqual(runtime.sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment( Screen1.Lit37), Screen1.Lit22)), v5) != Boolean.FALSE) { runtime.callComponentMethod(Screen1.Lit53, Screen1.Lit54, LList.list3("Please Enter the Name", "Error", "Ok"), Screen1.Lit55); runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Screen1.Lit37), Screen1.Lit22, v5, Screen1.Lit20); v0 = runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment(Screen1.Lit47), Screen1.Lit22, v5, Screen1.Lit20); } else { while(runtime.callYailPrimitive(Scheme.numLEq, LList.list2(runtime.lookupInCurrentFormEnvironment( Screen1.Lit12), runtime.callYailPrimitive(strings.string$Mnlength, LList.list1(runtime .sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment( Screen1.Lit37), Screen1.Lit22))), Screen1.Lit56, "length")), Screen1.Lit57, "<=") != Boolean.FALSE) { runtime.addToCurrentFormEnvironment(Screen1.Lit10, runtime.callComponentMethod(Screen1 .Lit58, Screen1.Lit59, LList.list1(runtime.callComponentMethod(Screen1.Lit58, Screen1.Lit60, LList.Empty, LList.Empty)), Screen1.Lit61)); runtime.addToCurrentFormEnvironment(Screen1.Lit14, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Screen1.Lit14), runtime.callYailPrimitive( MultiplyOp.$St, LList.list2(runtime.lookupInCurrentFormEnvironment(Screen1.Lit10), runtime.lookupInCurrentFormEnvironment(Screen1.Lit12)), Screen1.Lit62, "*")), Screen1.Lit63, v7)); runtime.addToCurrentFormEnvironment(Screen1.Lit14, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Screen1.Lit14), runtime.callYailPrimitive( numbers.modulo, LList.list2(runtime.lookupInCurrentFormEnvironment(Screen1.Lit14), Screen1.Lit64), Screen1.Lit65, "modulo")), Screen1.Lit66, v7)); runtime.addToCurrentFormEnvironment(Screen1.Lit12, runtime.callYailPrimitive(AddOp.$Pl, LList.list2(runtime.lookupInCurrentFormEnvironment(Screen1.Lit12), Screen1.Lit28), Screen1.Lit67, v7)); } v0 = runtime.isYailEqual(runtime.sanitizeComponentData(Invoke.invoke.apply2(runtime.lookupInCurrentFormEnvironment( Screen1.Lit47), Screen1.Lit22)), runtime.lookupInCurrentFormEnvironment(Screen1. Lit14)) != Boolean.FALSE ? runtime.$PcSetAndCoerceProperty$Ex(runtime.lookupInCurrentFormEnvironment( Screen1.Lit0), Screen1.Lit16, Screen1.Lit68, Screen1.Lit18) : runtime.$PcSetAndCoerceProperty$Ex( runtime.lookupInCurrentFormEnvironment(Screen1.Lit0), Screen1.Lit16, Screen1.Lit69, Screen1.Lit18); } return v0; }分析代码后发现,开头有2句比较关键。拿出开头的两句:runtime.addToCurrentFormEnvironment(Lit12, Lit28);runtime.addToCurrentFormEnvironment(Lit14, Lit11);通过分析可以发现这里给变量赋值了,所以继续追踪:发现Lit12就是”tam_nombre” Screen1.Lit34 = IntNum.make(-2); Screen1.Lit33 = SimpleSymbol.valueOf("Width"); Screen1.Lit32 = IntNum.make(3); Screen1.Lit31 = SimpleSymbol.valueOf("FontTypeface"); Screen1.Lit30 = IntNum.make(14); Screen1.Lit29 = SimpleSymbol.valueOf("FontSize"); Screen1.Lit28 = IntNum.make(1); Screen1.Lit27 = SimpleSymbol.valueOf("Alignment"); Screen1.Lit26 = SimpleSymbol.valueOf("Label1"); Screen1.Lit25 = new FString("com.google.devtools.simple.runtime.components.android.Label"); Screen1.Lit24 = SimpleSymbol.valueOf("Initialize"); Screen1.Lit23 = SimpleSymbol.valueOf("Screen1$Initialize"); Screen1.Lit22 = SimpleSymbol.valueOf("Text"); Screen1.Lit21 = SimpleSymbol.valueOf("lbl_rules"); Screen1.Lit19 = SimpleSymbol.valueOf("Title"); int[] v0_1 = new int[2]; v0_1[0] = -14336; Screen1.Lit17 = IntNum.make(v0_1); Screen1.Lit16 = SimpleSymbol.valueOf("BackgroundColor"); Screen1.Lit15 = SimpleSymbol.valueOf("nombre"); Screen1.Lit14 = SimpleSymbol.valueOf("temp"); Screen1.Lit13 = SimpleSymbol.valueOf("serial"); Screen1.Lit12 = SimpleSymbol.valueOf("tam_nombre"); Screen1.Lit11 = IntNum.make(0); Screen1.Lit10 = SimpleSymbol.valueOf("ano"); Screen1.Lit9 = SimpleSymbol.valueOf("*the-null-value*"); Screen1.Lit8 = SimpleSymbol.valueOf("getErrorType"); Screen1.Lit7 = SimpleSymbol.valueOf("get"); Screen1.Lit6 = SimpleSymbol.valueOf("show"); Screen1.Lit5 = IntNum.make(5); Screen1.Lit4 = SimpleSymbol.valueOf("getMessage"); Screen1.Lit3 = SimpleSymbol.valueOf("makeText"); Screen1.Lit2 = Toast.class; Screen1.Lit1 = SimpleSymbol.valueOf("repl"); Screen1.Lit0 = SimpleSymbol.valueOf("Screen1");
所以有:
tam_nombre = 1
temp = 0
如果用户不输入一个name的话,他会显示出错,“请输入用户名”。看下一个条件中的判断语句,出现了一个numLEq,从字面上理解为“小于等于”。
分析代码发现其实判断条件为:
while(tam_nombre <= len(nombre)) 即为while(1<= len(nombre))
从这里可以知道,name的长度至少要1位既可以满足条件。
同样的方法,我们继续分析下一个判断可以知道,计算出来的序列号储存在temp中。
给出一组序列号:
Username:Ericky
Password:47652
KeygenCode:public class Keygen {public static void main(String[] args) {int namelength =args[0].length();// TODO Auto-generated method stubint tam_nombre = 1;int temp = 0;int ano = 2014;while(tam_nombre<=namelength ){temp += ano * tam_nombre;temp += temp % 1638;tam_nombre += 1;}System.out.println("Serial : "+temp);}}
后面还有2个给大家玩吧~累 休息
总的来说主要提高了对smali代码的熟练度~收获还不错,纠正了一些理解上的偏差和巩固了之前的smali。(*^__^*)
BY Ericky
2014.12.6
- Android Crackme分析
- CrackMe的算法分析
- crackMe的逆向分析
- 一个CrackMe的分析
- CrackMe on Android
- 无提示CrackMe算法分析
- 一个简单的CrackMe分析
- 一个简单的CrackMe分析
- CrackMe技术等级自测3级一个CrackMe分析
- android-crackme-challenge write-up
- 再一个CrackMe的算法分析
- crackme算法分析---CRC32算法的妙用
- No.1 入门级CrackMe分析
- 第一枚ARM汇编版CrackMe分析
- 趣味CRACKME破解分析(发散思维)
- 一个简单CrackMe分析+keyGen编写
- 一个含有crc32算法的CrackMe分析
- 简单CrackMe分析(样本名:ReverseMe)
- HDU_3565 Are You Busy(DP,状态转换)
- 杭电2039 三角形
- jsp页面特殊字符展示处理
- 中文传参乱码问题解决思路
- 《第一行代码-Android》学习笔记(一)
- Android Crackme分析
- 《第一行代码-Android》学习笔记(二)
- 极大化思想解决最大子矩形问题
- 《第一行代码-Android》学习笔记(三)
- 《第一行代码-Android》学习笔记(四)
- bs+json解析
- 五大算法之(2)动态规划
- kazoo在多进程下使用全局连接死锁问题
- 《第一行代码-Android》学习笔记(五)