哇比起Lab3可以说是很痛苦了…
康康Smali转Java叭~
Task 1
这里是写了一个check输入字符串的类
public class Checker {
private String secret;
public Checker(){
secret="key";};//构造函数
private boolean checkStr1(String str)
{
int i=0,num=0,first=0,last=0;
char[] c=str.toCharArray();
int len=c.length;
while(i<len)
{
if(c[i]==0x78) {
num++;
if(num==1) first=i;
if(num==2) last=i;}
i++;}
if(num!=2 || (last-first)!=4 || c[0]!=0x30 || c[len-1]!=0x39) return false;
String tmp = str.substring(0, first);
if(tmp.contains(secret)) {
return true; }
else return false;
};//检查子串1
private int count(String str)
{
char[] c=str.toCharArray();
int len=c.length;
if(len<=0) return 0;
int i=0,num=0;
while(i<len)
{
if(c[i]==0x31) num++;
i++;
}
return num;
}//子串2中1的数量
private int func(int n)
{
if(n<=1) return 1;
else return func(n-1)*n;
}//阶乘
public boolean check(String str)
{
int len=str.length();
if(len<0xc) return false;
if(len<=0x10)
{
String sub1=str.substring(0,0xa);
String sub2=str.substring(0xa,len);
int m=count(sub2);
int k=func(m);
if(m==k && checkStr1(sub1)==true) return true;
else return false;
}
else return false;
}
}
其实很容易看懂的
输入一个字符串,长度在12~16之间,分成两个子串分别check:
(1)(0~0xa)用checkStr1
开头0,结尾9,中间有两个x中间间隔3个字符,第一个x之前含"key"
eg.0keyxabcx9
(2)(0xa~结尾)用count() & func()
需要含有k个1(k满足k==k!)
eg.11abc
输出:
ps:写的时候有几个小错误没注意,debug了挺久的…
第一个是first和last的值没有更新对,其实是在不等于x的时候也进行判断(悔恨的泪水( •̥́ ˍ •̀ू ))
(强行smali输出debug)
第二个是我写的0和0!是相等的…(又粗心( •̥́ ˍ •̀ू )
看反汇编要仔细仔细仔细!!
Task 2
第二关相对复杂,先输入ID,生成hash值并encode
会给出一个Encoded msg
然后需要把这个msg作为参数运行,再输入ID判断是否合法
public class Encoder {
private String algorithm;
private String charSet;
private final String[] hexDigits;
public Encoder()
{
hexDigits= new String[]{
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
algorithm="MD5";
charSet="utf-8";
}//构造函数
private String byteArrayToHexString(byte[] b)
{
StringBuffer buff = new StringBuffer();
int len=b.length,i=0;
while(i<len)
{
buff.append(byteToHexString(b[i]));
i++;
}
return buff.toString();
}//转换HexString
private String byteToHexString(Byte b)
{
int b1=b&0xff;
int v0=b1/16,v1=b1%16;
StringBuilder build=new StringBuilder();
build.append(hexDigits[v0]).append(hexDigits[v1]);
return build.toString();
}
private String getSalt()
{
Random ran=new Random();
StringBuilder build=new StringBuilder(0x10);
int i=0;
while(i<0x10)
{
if(ran.nextBoolean()==false)
build.append("0");
else build.append("1");
i++;
}
return build.toString();
}//获取盐值
public boolean check(String a,String b)
{
int i=0;
char[] c1=new char[0x20];
char[] c2=new char[0x10];
int b_len=b.length();
if(b_len!=0x30) return false;
else {
while (i<0x30) {
int m=(i/3)*2;
c1[m]=b.charAt(i);
c1[m+1]=b.charAt(i+2);
m=i/3;
c2[m]=b.charAt(i+1);
i+=3;
}
String str = new String(c2);
StringBuilder build1 = new StringBuilder();
build1.append(a).append(str);
String str1 = build1.toString();
try {
MessageDigest dig = MessageDigest.getInstance(algorithm);
StringBuilder build2 = new StringBuilder();
build2.append("");
byte[] res = dig.digest(str1.getBytes(charSet));
build2.append(byteArrayToHexString(res));
String str2 = new String(c1);
return str2.equals(build2.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}//用于第二次检查
public String encoding(String str){
String salt=getSalt();
String str2=null;
String str3=null;
StringBuilder build=new StringBuilder();
StringBuilder build2 = new StringBuilder();
build.append(str).append(salt);
String str1=build.toString();
try{
MessageDigest dig = MessageDigest.getInstance(algorithm);
build2.append("");
byte[] res = dig.digest(str1.getBytes(charSet));
build2.append(byteArrayToHexString(res));
str2=build2.toString();
} catch (Exception e) {
e.printStackTrace();}
try{
char[] c=new char[0x30];
int i=0;
while(i<0x30)
{
int m=(i/3)*2;
c[i]=str2.charAt(m);
m=i/3;
c[i+1]=salt.charAt(m);
m=(i/3)*2+1;
c[i+2]=str2.charAt(m);
i+=3;
}
str3=new String(c);} catch (Exception e) {
str3=str2;
e.printStackTrace();
}
return str3;
}//用于第一次生成Encoded msg
}
还蛮好理解的,就是在加密时用了一些Java的自动加密方法
idea带参数的方法:
https://blog.csdn.net/u013713294/article/details/53020293
以及发现了很有意思的事情,传入byte参数<0时会&0xff
查了一下资料:
https://blog.csdn.net/ido1ok/article/details/85235955
大概就是之后作为int运算时byte自动补符号位吧,&一下保证得到正数
当中的一些加密方法:(hash)
MessageDigest.getInstance(algorithm);
生成实现指定摘要算法的 MessageDigest 对象
digest(byte[] input)
使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
其实这些都是之后要学的加密方法啦~
输出: