2016Tencent初赛Android移动端
1.java层
java层没有什么特殊的地方,so层返回一个参数为0,或1,执行Toast
进入libCheckRegister.so
2.so层
分析发现so层是将name进行加密,并和pass非标准的base64解密后的结果进行比较,table为
private static byte[] table = {
0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, 0x00
};
通过
while ( (unsigned __int8)encodeTable[(unsigned __int8)*(pPass - 1)] <= 0x3Fu );
取出表中的有用的值,然后进行如下的变换
finalPass[4]+finalName[0]==finalPass[2]
finalName[0]+finalName[1]==finalPass[4]
finalName[2]+finalPass[3]==finalPass[0]
finalName[2]+finalName[3]==finalPass[3]
finalName[4]+finalPass[1]-3finalName[2]<=0
由finalName–>finalPass
finalPass[4]==finalName[0]+finalName[1]
finalPass[2]==finalName[0]+finalPass[4]
finalPass[3]==finalName[4]+finalName[3]
finalPass[0]==finalName[2]+finalPass[3]
finalPass[1]<=3finalName[2]-finalName[4]
finalPass由pass经过base64decode得到
finalName ->某种变换
3.根据上述分析编写脚本
最后编写解密脚本
ctfdecrypt.java
import java.util.Scanner;
public class ctfdecrypt {
private static byte[] name = null;
private String code = null;
private static int[] nameCrypt1 = null;
private static int[] nameCrypt2 = null;
private static int[] codeCrypt1 = null;
private static byte[] codeCrypt2 = null;
private byte[] resByte = null;
private static byte[] table = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3E,0x40,0x40,0x40,0x3F,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0,1,2,3,4,5,6,7,8,9,0xA,0xB,0xC,0xD,0xE,0xF,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x40,0x40,0x40,0x40,0x40,0x40,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
public ctfdecrypt(String n) throws Exception{
this.name = n.getBytes();
if (this.name.length < 6 || this.name.length > 20) {
System.out.println("请输入6-20的长度");
throw new Exception();
}
nameCrypt1 = new int[23];
nameCrypt2 = new int[5];
codeCrypt1 = new int[5];
resByte = new byte[50];
codeCrypt2 = new byte[30];
}
public static void namedecode() {
int tmp = 0;
int i = 0, j = 0;
for (; i < 16; i++, j = i % name.length) {
nameCrypt1[i] = ((name[j] * (0x1339e7e + i) * name.length) + tmp) & 0x0ff;
tmp = (((name[j] * (0x1339e7e + i) * name.length) + tmp) >> 0x8) & 0x00ffffff;
}
nameCrypt1[i++] = tmp & 0x0ff;
nameCrypt1[i++] = (tmp & 0x0ff00) >> 8;
nameCrypt1[i++] = (tmp & 0x0ff0000) >> 16;
for (i = 0; i < 5; i++) {
nameCrypt2[i] = nameCrypt1[i * 4 + 3];
nameCrypt2[i] = nameCrypt2[i] << 8 | nameCrypt1[i * 4 + 2];
nameCrypt2[i] = nameCrypt2[i] << 8 | nameCrypt1[i * 4 + 1];
nameCrypt2[i] = nameCrypt2[i] << 8 |nameCrypt1[i * 4];
}
for (i = 0; i < 5; i++) {
nameCrypt2[i] = nameCrypt2[i] / 10;
}
}
public static String getCode() {
StringBuilder sb = new StringBuilder();
codeCrypt1[3] = nameCrypt2[2] + nameCrypt2[3];
codeCrypt1[0] = codeCrypt1[3] + nameCrypt2[2];
codeCrypt1[1] = 3 * nameCrypt2[2] - nameCrypt2[4];
codeCrypt1[4] = nameCrypt2[0] + nameCrypt2[1];
codeCrypt1[2] = codeCrypt1[4] + nameCrypt2[0];
for (int i = 0; i < 5; i++) {
codeCrypt2[i * 4] = (byte) ( codeCrypt1[i] & 0x0ff);
codeCrypt2[i * 4 + 1] = (byte) (( codeCrypt1[i] >> 8) & 0x0ff);
codeCrypt2[i * 4 + 2] = (byte) (( codeCrypt1[i] >> 16) & 0x0ff);
codeCrypt2[i * 4 + 3] = (byte) (( codeCrypt1[i] >> 24) & 0x0ff);
}
for (int i = 0; i <= 6; i++) {
byte tmp = 0;
if (i == 6) {
tmp = (byte) ((codeCrypt2[i * 3] & 0x0ff) >> 2);
sb.append((char) SearchTable(tmp));
tmp = (byte) (((codeCrypt2[i * 3] & 0x03) << 4) | ((codeCrypt2[i * 3 + 1] >> 4)) & 0x0f);
sb.append((char) SearchTable(tmp));
tmp = (byte) (((codeCrypt2[i * 3 + 1] & 0xf) << 2) | ((codeCrypt2[i * 3 + 2] & 0x0ff) >> 6));
sb.append((char) SearchTable(tmp));
} else {
tmp = (byte) ((codeCrypt2[i * 3] & 0x0ff) >> 2);
sb.append((char) SearchTable(tmp));
tmp = (byte) (((codeCrypt2[i * 3] & 0x03) << 4) | ((codeCrypt2[i * 3 + 1] >> 4)) & 0x0f);
sb.append((char) SearchTable(tmp));
tmp = (byte) (((codeCrypt2[i * 3 + 1] & 0xf) << 2) | ((codeCrypt2[i * 3 + 2] & 0x0ff) >> 6));
sb.append((char) SearchTable(tmp));
tmp = (byte) (codeCrypt2[i * 3 + 2] & 0x3f);
sb.append((char) SearchTable(tmp));
}
}
return sb.toString();
}
private static int SearchTable(byte content) {
for (int i = 0; i < 256; i++) {
if (table[i] == content) {
return i;
} else {
continue;
}
}
return -1;
}
}
Main.java
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入姓名:");
String name=scanner.next();
ctfdecrypt c=new ctfdecrypt(name);
c.namedecode();
System.out.println("那么密码为:"+c.getCode());
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191218131204553.png)
这里的脚本采用的是java,最开始打算使用C++来编写的,但是无奈太菜,日后有时间在补上