攻防世界-eastjni-Writeup

eastjni

考点:自定义密码表base加密、so

分析

前面的怎么定位 java 层关键位置就略过,查一下错误弹窗就能找到。

输入字符串会作为 mainactivity/a 的参数输入:

private boolean a(String paramString)
{
    try
    {
        a locala = new com/a/easyjni/a;
        locala.<init>();
        bool = ncheck(locala.a(paramString.getBytes()));
        return bool;
    }
    catch (Exception paramString)
    {
        for (;;)
        {
            boolean bool = false;
        }
    }
}

然后又作为 com/a/easyjni/a 的参数输入,到达第一层加密:

public class a
{
  private static final char[] a = { 105, 53, 106, 76, 87, 55, 83, 48, 71, 88, 54, 117, 102, 49, 99, 118, 51, 110, 121, 52, 113, 56, 101, 115, 50, 81, 43, 98, 100, 107, 89, 103, 75, 79, 73, 84, 47, 116, 65, 120, 85, 114, 70, 108, 86, 80, 122, 104, 109, 111, 119, 57, 66, 72, 67, 77, 68, 112, 69, 97, 74, 82, 90, 78 };
  
  public String a(byte[] paramArrayOfByte)
  {
    StringBuilder localStringBuilder = new StringBuilder();
    for (int i = 0; i <= paramArrayOfByte.length - 1; i += 3)
    {
      byte[] arrayOfByte = new byte[4];
      int j = 0;
      int k = 0;
      if (j <= 2)
      {
        if (i + j <= paramArrayOfByte.length - 1) {
          arrayOfByte[j] = ((byte)(byte)(k | (paramArrayOfByte[(i + j)] & 0xFF) >>> j * 2 + 2));
        }
        for (k = (byte)(((paramArrayOfByte[(i + j)] & 0xFF) << (2 - j) * 2 + 2 & 0xFF) >>> 2);; k = 64)
        {
          j++;
          break;
          arrayOfByte[j] = ((byte)k);
        }
      }
      arrayOfByte[3] = ((byte)k);
      k = 0;
      if (k <= 3)
      {
        if (arrayOfByte[k] <= 63) {
          localStringBuilder.append(a[arrayOfByte[k]]);
        }
        for (;;)
        {
          k++;
          break;
          localStringBuilder.append('=');//base
        }
      }
    }
    return localStringBuilder.toString();
  }
}

每一个字符都进行一次加密,每轮加密都会有 & 、>> 操作,且最后会加上 == ,推断是 base 加密。然后根据密码表 a 判断是自定义密码表的 base 加密方式。

第一次加密完成后的返回值作为 ncheck 的参数,这是一个加载的 so 中的函数:System.loadLibrary("native");。分析这个函数需要到 so 文件里面,so 文件在 lib/armeabi-v7a/libnative.so 。

进入到 ncheck 函数后,再进行两次加密,分别是:前 16 位与后 16 位互换;前 1 位与后 1 位互换:

signed int __fastcall Java_com_a_easyjni_MainActivity_ncheck(int a1, int a2, int a3)
{
…………
  v6 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);// 字符串传递给a1,a1指针取值到v6
  if ( strlen(v6) == 32 )                       // base加密长度限制32位
  {
    v7 = 0;
    do
    {
      v8 = &s1[v7];                             // s1[0]指针给v8
      s1[v7] = v6[v7 + 16];                     // s1[0]=v6[16]
      v9 = v6[v7++];
      v8[16] = v9;                              // s1[0+16]=v6[0]
    }
    while ( v7 != 16 );                         // 循环16次,每次操作两个数
                                                // 相当于将前16位于后16位对调
    (*(void (__fastcall **)(int, int, const char *))(*(_DWORD *)v4 + 680))(v4, v5, v6);
    v10 = 0;
    do
    {
      v12 = __OFSUB__(v10, 30);
      v11 = v10 - 30 < 0;
      v16 = s1[v10];
      s1[v10] = s1[v10 + 1];                    // s1[0]=s1[1]
      s1[v10 + 1] = v16;                        // s1[1]=s1[0]
      v10 += 2;
    }
    while ( v11 ^ v12 );                        // 相当于前一位与后一位对调位置
    v13 = memcmp(s1, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u);//与密文比较
…………
}
思路

首先将密文:MbT3sQgX039i3g==AQOoMQFPskB1Bsc7 还原:

#手动完成前后 16 位互换
c = list("AQOoMQFPskB1Bsc7MbT3sQgX039i3g==")
for i in range(0,len(c),2):
	v9 = c[i]
	c[i] = c[i+1]
	c[i+1] = v9
c = ''.join(c)
print("flag:{}".format(c))
#flag:QAoOQMPFks1BsB7cbM3TQsXg30i9g3==

然后实现自定义密码表 base 解码,我找到的一个脚本:

# coding:utf-8

# 自定义加密表
#s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"#原版
s = "i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN"#自定义

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)

运行结果:

     *************************************
     *    (1)encode         (2)decode    *
     *************************************

Please select the operation you want to perform:
2
Please enter a string that needs to be decrypted:
QAoOQMPFks1BsB7cbM3TQsXg30i9g3==
Decrypted String:
flag{实践出真知这不是flag}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值