【攻防世界】mobile easy-so writeup

44 篇文章 0 订阅
10 篇文章 0 订阅

从下面的代码知道,它调用了cyberspace的CheckString方法,而这个CheckString调用了so里的函数。

public class MainActivity extends AppCompatActivity {
    @Override  // android.support.v7.app.AppCompatActivity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F09001B);  // layout:activity_main
        ((Button)this.findViewById(0x7F070022)).setOnClickListener(new View.OnClickListener() {  // id:button
            @Override  // android.view.View$OnClickListener
            public void onClick(View v) {
                if(cyberpeace.CheckString(((EditText)MainActivity.this.findViewById(0x7F070031)).getText().toString()) == 1) {  // id:editText
                    Toast.makeText(MainActivity.this, "验证通过!", 1).show();
                    return;
                }

                Toast.makeText(MainActivity.this, "验证失败!", 1).show();
            }
        });
    }
}

CheckString方法里J_TestDec方法,用于对传入的字符串做处理

int __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(int a1, int a2, int a3)
{
  int v3; // r8
  const char *v4; // r9
  size_t len; // r6
  char *v6; // r5

  v3 = 0;
  v4 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
  len = strlen(v4);
  v6 = (char *)malloc(len + 1);
  memset(&v6[len], 0, len != -1);
  qmemcpy(v6, v4, len);
  j_TestDec((int)v6);
  if ( !strcmp(v6, "f72c5a36569418a20907b55be5bf95ad") )
    v3 = 1;
  return v3;
}
size_t __fastcall TestDec(char *a1)
{
  size_t i; // r5
  unsigned __int8 *v3; // r1
  unsigned __int8 v4; // r0
  size_t result; // r0
  int v6; // r5
  unsigned __int8 *v7; // r0
  unsigned __int8 v8; // r1
  size_t v9; // r1

  if ( strlen(a1) >= 2 )
  {
    i = 0;
    do
    {
      v3 = (unsigned __int8 *)&a1[i];
      v4 = a1[i];
      a1[i] = a1[i + 16];
      ++i;
      v3[16] = v4;
    }
    while ( i < strlen(a1) >> 1 );
  }
  result = (unsigned __int8)*a1;
  if ( *a1 )
  {
    *a1 = a1[1];
    a1[1] = result;
    result = strlen(a1);
    if ( result >= 3 )
    {
      v6 = 0;
      do
      {
        v7 = (unsigned __int8 *)&a1[v6];
        v8 = a1[v6 + 2];
        v7[2] = a1[v6 + 3];
        v7[3] = v8;
        result = strlen(a1);
        v9 = v6 + 4;
        v6 += 2;
      }
      while ( v9 < result );
    }
  }
  return result;
}

上面的c++代码有点乱,为了方便理解,我用python代码重写了

def TestDec(a1):  
    # 将字符串转换为字符列表  
    a1 = list(a1)  
    length = len(a1)  
    i = 0  
    while length - i >= 17:  
        tmp = a1[i]  
        a1[i] = a1[i + 16]  
        a1[i + 16] = tmp  
        i += 1  
    result = ord(a1[0])   
    if result > 0:  
        a1[0] = a1[1]  
        a1[1] = chr(result)   
        result = len(a1)  # 这里result变成了列表的长度  
        v9 = 2  # 从2开始,因为我们已经处理了前两个字符  
        if result >= 3:  
            v6 = 0  
            while v6 < result - 2:  # 确保不会越界  
                tmp = a1[v6 + 2]  
                a1[v6 + 2] = a1[v6 + 3]  
                a1[v6 + 3] = tmp  
                v6 += 2

这样就很容易理解,它主要是用于交换输入字符串的字符。下面是它的逆向,输出就是flag

def reverse_test_dec(result):    
    a1 = bytearray(result, 'utf-8')  
      
    # 逆向第二个交换操作  
    length = len(a1)  
    v6 = 0  
    v9 = 0  
    if length >= 3:  
        while v9 < length:  
            tmp = a1[v6 + 2]  
            a1[v6 + 2] = a1[v6 + 3]  
            a1[v6 + 3] = tmp  
            v6 += 2  
            v9 = v6 + 2  # 更新v9以匹配原始while循环的条件  
      
    # 逆向第一个交换操作和字符交换  
    if a1[0] > 0:  # 这里应该检查字符是否为空,但在Python中应使用if a1[0] != 0 or a1[0] != ord(''):  
        tmp = a1[0]  
        a1[0] = a1[1]  
        a1[1] = tmp  
          
        # 逆向主要的字符交换操作  
        i = 0  
        while length - i >= 17:  
            tmp = a1[i]  
            a1[i] = a1[i + 16]  
            a1[i + 16] = tmp  
            i += 1  
      
    # 将字节数组转换回字符串并返回  
    return a1.decode('utf-8')  # 注意:这里假设原始字符串是UTF-8编码的  
    
result_str = "f72c5a36569418a20907b55be5bf95ad"   
original_str = reverse_test_dec(result_str)    
print(original_str)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值