XCTF-mobile

easy-apk

new Base64New().Base64Encode(((EditText)
MainActivity.this.findViewById(R.id.editText)).
getText().toString().getBytes()).equals
("5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs=")

由关键代码可知,是一串字符在base64 加密后与"5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs="匹配,那么可以逆向将已知密文串base64 解密获得输入明文


由Base64NEW包可得到新base64 算法,发现其更改了码表

原来:s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
新码表: s = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/"

python脚本实现解码

# coding:utf-8
 
#s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
s = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/"
 
def My_base64_encode(inputs):
	# 将字符串转化为2进制
	bin_str = []
	for i in inputs:
		x = str(bin(ord(i))).replace('0b', '')
		bin_str.append('{:0>8}'.format(x))
	#print(bin_str)
	# 输出的字符串
	outputs = ""
	# 不够三倍数,需补齐的次数
	nums = 0
	while bin_str:
		#每次取三个字符的二进制
		temp_list = bin_str[:3]
		if(len(temp_list) != 3):
			nums = 3 - len(temp_list)
			while len(temp_list) < 3:
				temp_list += ['0' * 8]
		temp_str = "".join(temp_list)
		#print(temp_str)
		# 将三个8字节的二进制转换为4个十进制
		temp_str_list = []
		for i in range(0,4):
			temp_str_list.append(int(temp_str[i*6:(i+1)*6],2))
		#print(temp_str_list)
		if nums:
			temp_str_list = temp_str_list[0:4 - nums]
			
		for i in temp_str_list:
			outputs += s[i]
		bin_str = bin_str[3:]
	outputs += nums * '='
	print("Encrypted String:\n%s "%outputs)
	
def My_base64_decode(inputs):
	# 将字符串转化为2进制
	bin_str = []
	for i in inputs:
		if i != '=':
			x = str(bin(s.index(i))).replace('0b', '')
			bin_str.append('{:0>6}'.format(x))
	#print(bin_str)
	# 输出的字符串
	outputs = ""
	nums = inputs.count('=')
	while bin_str:
		temp_list = bin_str[:4]
		temp_str = "".join(temp_list)
		#print(temp_str)
		# 补足8位字节
		if(len(temp_str) % 8 != 0):
			temp_str = temp_str[0:-1 * nums * 2]
		# 将四个6字节的二进制转换为三个字符
		for i in range(0,int(len(temp_str) / 8)):
			outputs += chr(int(temp_str[i*8:(i+1)*8],2))
		bin_str = bin_str[4:]	
	print("Decrypted String:\n%s "%outputs)
	
print()
print("     *************************************")
print("     *    (1)encode         (2)decode    *")	
print("     *************************************")
print()
 
 
num = input("Please select the operation you want to perform:\n")
if(num == "1"):
	input_str = input("Please enter a string that needs to be encrypted: \n")
	My_base64_encode(input_str)
else:
	input_str = input("Please enter a string that needs to be decrypted: \n")
	My_base64_decode(input_str)

或者用

#使用python2运行
#若使用python3.4以上,需把string.maketrans改为str.maketrans

import base64

import string

string1 = string.maketrans("vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/",
                           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
strEnBase64 = "5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs=".translate(string1)

print(strEnBase64)

strFlag = base64.b64decode(strEnBase64)

print(strFlag.decode("utf-8")

获得明文

05397c42f9b6da593a3644162d36eb01

加上flag{}

flag{05397c42f9b6da593a3644162d36eb01}

easy-so


发现使用cyberpeace类中CheckString关键函数


于cyberpeace类找到函数,可以看出使用native函数CheckString,判断在so层实现该函数,拿出加载库so文件,用ida反编译得下图


拿出代码

_BOOL4 __cdecl Java_com_testjava_jack_pingan2_cyberpeace_CheckString(int a1, int a2, int a3)
{
  size_t v3; // edi
  char *v4; // esi
  size_t v5; // edi
  char v6; // al
  char v7; // al
  size_t v8; // edi
  char v9; // al
  const char *v11; // [esp+18h] [ebp-14h]

  v11 = (const char *)(*(int (__cdecl **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
  v3 = strlen(v11);//取字符串长
  v4 = (char *)malloc(v3 + 1);//申请内存
  memset(&v4[v3], 0, v3 != -1);
  memcpy(v4, v11, v3);//拷贝赋值
  if ( strlen(v4) >= 2 )
  {
    v5 = 0;
    do
    {
      v6 = v4[v5];
      v4[v5] = v4[v5 + 16];
      v4[v5++ + 16] = v6;//前十六字符与后十六字符置换
    }
    while ( v5 < strlen(v4) >> 1 );//直到字符串结束
  }
  v7 = *v4;
  if ( *v4 )
  {
    *v4 = v4[1];
    v4[1] = v7;//第一个字符与第零个字符置换
    if ( strlen(v4) >= 3 )
    {
      v8 = 2;
      do
      {
        v9 = v4[v8];//从第二个字符开始
        v4[v8] = v4[v8 + 1];//后一个字符
        v4[v8 + 1] = v9;//前后交换
        v8 += 2;//隔两个数递增
      }
      while ( v8 < strlen(v4) );//直到字符末尾结束
    }
  }
  return strcmp(v4, "f72c5a36569418a20907b55be5bf95ad") == 0;
}

写个python跑出来

a="f72c5a36569418a20907b55be5bf95ad"
a=list(a);
for i in range(0,len(a),2):
    b=a[i]
    a[i]=a[i+1]
    a[i+1]=b
b=a[:16]
a[:16]=a[16:]
a[16:]=b
a=''.join(a)
print (a)

得到结果

90705bb55efb59da7fc2a5636549812a

flag{90705bb55efb59da7fc2a5636549812a}

easyjni

根据入口找到a函数

package com.a.easyjni;

public class a {
    private static final char[] a = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'};

    public String a(byte[] bArr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i <= bArr.length - 1; i += 3) {
            byte[] bArr2 = new byte[4];
            byte b = 0;
            for (int i2 = 0; i2 <= 2; i2++) {
                if (i + i2 <= bArr.length - 1) {
                    bArr2[i2] = (byte) (b | ((bArr[i + i2] & 255) >>> ((i2 * 2) + 2)));
                    b = (byte) ((((bArr[i + i2] & 255) << (((2 - i2) * 2) + 2)) & 255) >>> 2);
                } else {
                    bArr2[i2] = b;
                    b = 64;
                }
            }
            bArr2[3] = b;
            for (int i3 = 0; i3 <= 3; i3++) {
                if (bArr2[i3] <= 63) {
                    sb.append(a[bArr2[i3]]);
                } else {
                    sb.append('=');
                }
            }
        }
        return sb.toString();
    }
}

与easy-apk类似,使用base64加密,并且改了码表

#python2运行

import base64
 
import string
 
string1=string.maketrans("i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")

strEnBase64 = "QAoOQMPFks1BsB7cbM3TQsXg30i9g3==".translate(string1)
 
print(strEnBase64)
 
strFlag = base64.b64decode(strEnBase64)
 
print(strFlag.decode("utf-8")

得到flag

flag{just_ANot#er_@p3}

apk逆向

jd龟打开,入口好找


找到检查函数checkSN

 public boolean checkSN(String userName, String sn) {
        if (userName == null) {
            return false;
        }
        try {
            if (userName.length() == 0 || sn == null || sn.length() != 22) {	//输入的username不空,sn必须22位
                return false;
            }
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.reset();
            digest.update(userName.getBytes());		
            String hexstr = toHexString(digest.digest(), "");//将username的MD5值作为toHexString参数
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hexstr.length(); i += 2) {
                sb.append(hexstr.charAt(i));
            }
            if (("flag{" + sb.toString() + "}").equalsIgnoreCase(sn)) {
                return true;
            }
            return false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        }
    }
 private static String toHexString(byte[] bytes, String separator) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 255);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex).append(separator);
        }
        return hexString.toString();
    }
}

直接拿这些现有代码出来跑

package xctf_apk;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class apk {
	
	    private static String toHexString(byte[] bytes, String separator) {
	        StringBuilder hexString = new StringBuilder();
	        for (byte b : bytes) {
	            String hex = Integer.toHexString(b & 255);
	            if (hex.length() == 1) {
	                hexString.append('0');
	            }
	            hexString.append(hex).append(separator);
	        }
	        return hexString.toString();
	    }
	    
	    public static void main(String[] args) throws NoSuchAlgorithmException {
	    	String username="Tenshine";
	    	 MessageDigest digest = MessageDigest.getInstance("MD5");
	            digest.reset();
	            digest.update(username.getBytes());
	            String hexstr = toHexString(digest.digest(), "");
	            StringBuilder sb = new StringBuilder();
	            for (int i = 0; i < hexstr.length(); i += 2) {
	                sb.append(hexstr.charAt(i));
	            }
	            System.out.printf("flag{" + sb.toString() + "}") ;

	    }	
}

得到flag

flag{bc72f242a6af3857}

然后这题很坑

提交bc72f242a6af3857

人民的名义-抓捕赵汉德

拿到jar文件,用jd龟打开

找到关键代码

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    CheckInterface checkerObject = loadCheckerObject();//实现接口句柄
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    while (true) {
      System.out.println("Enter password:");
      String line = stdin.readLine();
      if (checkerObject.checkPassword(line)) {
        System.out.println("Well done, that is the correct password");
        System.exit(0);
        continue;
      } 
      System.out.println("Incorrect password");
    } 
  }

checkerObject.checkPassword(line)

找到接口类

发现checkPassword函数

从代码明显看出MD5操作,

将"fa3733c647dca53a66cf8df953c2d539"MD5解密即可

解密得monkey99

flag{monkey99}

Android基础

拿到apk,jadx龟打开

找MainActivicity,找到oncreate方法,发现关键函数checkPassword()

找到代码

public class Check {
    public boolean checkPassword(String str) {
        char[] pass = str.toCharArray();
        if (pass.length != 12) {	//12字符长
            return false;
        }
        for (int len = 0; len < pass.length; len++) {
            pass[len] = (char) (((255 - len) - 100) - pass[len]);//155-len
            if (pass[len] != '0' || len >= 12) {		//减了之后字符为0,对应ascii码48
                return false;
            }
        }
        return true;
    }
}

写个python跑出字符串

>>> key = list('000000000000')

>>> key
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']

>>> for i in range(12):
    value = 255 - 100 - i - ord(key[i])
    key[i] = chr(value)


>>> print("".join(str(i) for i in key))
kjihgfedcba` 

打开apk,输入kjihgfedcba` 验证

还要求输入显示码

回头看AndroidManifest.xml文件

找到触发动作

输入android.is.very.fun

得到flag