【Android 逆向】【攻防世界】android2.0

android,逆向,攻防,世界,android2 · 浏览次数 : 113

小编点评

**解题思路** 该程序通过将字符串分为三分,然后对每个分段进行处理,最终拼凑出最终字符串。以下是一些主要步骤: 1. 获取字符串的长度。 2. 将字符串分为三个部分。 3. 对每个部分进行处理。 4. 将所有部分拼接在一起。 **代码解析** **`Init`函数** 该函数将字符串分割为三个部分,并将它们存储在 `a5`, `a2` 和 `a3` 中。 ```c static int __fastcall Init(int result, char *a2, char *a3, const char *str_chars, int len) { int v5; int v6; int v7; if (len < 1) { v6 = 0; } else { v5 = 0; v6 = 0; do { v7 = v5 % 3; if (v5 % 3 == 2) { a3[v5 / 3u] = str_chars[v5]; } else if (v7 == 1) { a2[v5 / 3u] = str_chars[v5]; } else if ( !v7 ) { ++v6; *(_BYTE *)(result + v5 / 3u) = str_chars[v5]; } ++v5; } while (len != v5); } *(_BYTE *)(result + v6) = 0; a2[v6] = 0; a3[v6] = 0; return result; } ``` **`First`函数** 该函数检查字符串是否匹配预定义的字符串 "LN^dl"。 ```c static int __fastcall First(char *a1) { int i; for (i = 0; i != 4; ++i) { a1[i] = (2 * a1[i]) ^ 0x80; } return strcmp(a1, "LN^dl") == 0; } ``` **`second`函数** 该函数根据字符串的第一个字符构造其剩余部分。 ```c static void second() { a5 = [ord('f'), ord('g'), ord('o'), ord('r'), ord('l')] v5 = [ord('L'), ord('N'), ord('^'), ord('d'), ord('l')] v6 = "\"\"" for (i = 0; i < 4; ++i) { t = v5[i]^a5[i] v6 += (chr(t)) } v6 += 'a' print(v6) } ``` **`third`函数** 该函数根据字符串的第二和第三字符构造其剩余部分。 ```c static void third() { a6 = [ord('A'), ord('F'), ord('B'), ord('o'), ord('}')] v6 = [ord(' '), ord('5'), ord('-'), 0x16, ord('a')] for (i = 0; i < 4; ++i) { t = v6[i]^a6[i] v7 += (chr(t)) } v7 += '}' print(v7) } ``` **最终结果** 通过将以上三个函数连接起来,我们可以拼凑出最终字符串 "flag{sosorryla}"。

正文

这是一道纯算法还原题

1. apk安装到手机,提示输入flag,看来输入就是flag

2. jadx 打开apk查看

        this.button.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf03.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View v) {
                String str = MainActivity.this.pwd.getText().toString();
                int result = JNI.getResult(str);
                MainActivity.this.Show(result);
            }
        });

JNI.java

public class JNI {
    public static native int getResult(String str);

    static {
        System.loadLibrary("Native");
    }
}

3. IDA打开 libNative.so 看看

bool __fastcall Java_com_example_test_ctf03_JNI_getResult(JNIEnv *env, jclass a2, jstring str)
{
  int v3; // r4
  const char *str_chars; // r8
  char *v5; // r6
  char *v6; // r4
  char *v7; // r5
  int i; // r0
  int j; // r0

  v3 = 0;
  str_chars = (*env)->GetStringUTFChars(env, str, 0);
  if ( strlen(str_chars) == 15 )
  {
    v5 = (char *)malloc(1u);
    v6 = (char *)malloc(1u);
    v7 = (char *)malloc(1u);
    Init(v5, v6, v7, str_chars, 15);
    if ( !First(v5) )
      return 0;
    for ( i = 0; i != 4; ++i )
      v6[i] ^= v5[i];
    if ( !strcmp(v6, a5) )
    {
      for ( j = 0; j != 4; ++j )
        v7[j] ^= v6[j];
      return strcmp(v7, "AFBo}") == 0;
    }
    else
    {
      return 0;
    }
  }
  return v3;
}

先看一下Init函数在干什么

int __fastcall Init(int result, char *a2, char *a3, const char *str_chars, int len)
{
  int v5; // r5
  int v6; // r10
  int v7; // r6

  if ( len < 1 )
  {
    v6 = 0;
  }
  else
  {
    v5 = 0;
    v6 = 0;
    do
    {
      v7 = v5 % 3;
      if ( v5 % 3 == 2 )
      {
        a3[v5 / 3u] = str_chars[v5];
      }
      else if ( v7 == 1 )
      {
        a2[v5 / 3u] = str_chars[v5];
      }
      else if ( !v7 )
      {
        ++v6;
        *(_BYTE *)(result + v5 / 3u) = str_chars[v5];
      }
      ++v5;
    }
    while ( len != v5 );
  }
  *(_BYTE *)(result + v6) = 0;
  a2[v6] = 0;
  a3[v6] = 0;
  return result;
}

通过分析可知,该函数将字符串分为了三分,第一个字符给a1,第二个给a2,第三个给a3,第四个给a1,这样循环下去

再看First函数
bool __fastcall First(char *a1)
{
  int i; // r1

  for ( i = 0; i != 4; ++i )
    a1[i] = (2 * a1[i]) ^ 0x80;
  return strcmp(a1, "LN^dl") == 0;
}

这里是 拿着a对应的字符做个计算然后取和一个常量比较,这里可以倒推出a1的值,对应python

def first():
    b = "LN^dl"
    a1 = ''
    for i in range(0, 4):
        print(i)
        a1 += (chr(int((ord(b[i])^0x80)/2)))
    a1 += 'l'
    print(a1)

#得到 fgorl

注意这里得到了a1原来的值,但是这里a1已经被改了,值为"LN^dl", 我就在这里被坑到了

first函数过了之后,v6 做了一些计算,然后又和一个常量比较,那么又可以用上面的方法取干活
    for ( i = 0; i != 4; ++i )
      v6[i] ^= v5[i];
    if ( !strcmp(v6, a5) ){
    ......
    }

对应python

def second():
    a5 = [ord(' '),  ord('5'), ord('-'), 0x16, ord('a')]
    # v5 = [ord('f'), ord('g'), ord('o'), ord('r'), ord('l')]
    v5 = [ord('L'), ord('N'), ord('^'), ord('d'), ord('l')]
    v6 = ""
    for i in range(0, 4):
        t = v5[i]^a5[i]
        v6 += (chr(t))
    v6 += 'a'
    print(v6)

# 得到 l{sra

最后v7 也是一个套路,这里就直接给还原的代码了

def third():
    a6 = [ord('A'),  ord('F'), ord('B'), ord('o'), ord('}')]
    v6 = [ord(' '),  ord('5'), ord('-'), 0x16, ord('a')]
    v7 = ''
    for i in range(0, 4):
        t = v6[i]^a6[i]
        v7 += (chr(t))
    v7 += '}'
    print(v7)

# 得到 asoy}

最后把三个值拼起来,也就是最上面分析的那个循环赋值的逻辑,这里是还原算法

s1 = 'fgorl'
s2 = 'l{sra'
s3 = 'asoy}'
flag = ''
for i in range(5):
    flag += s1[i] + s2[i] + s3[i]
print(flag)

# 得到 flag{sosorryla}

与【Android 逆向】【攻防世界】android2.0相似的内容:

【Android 逆向】【攻防世界】android2.0

这是一道纯算法还原题 1. apk安装到手机,提示输入flag,看来输入就是flag 2. jadx 打开apk查看 this.button.setOnClickListener(new View.OnClickListener() { // from class: com.example.test

【Android 逆向】【攻防世界】RememberOther

1. apk安装到手机,提示输入用户名注册码 2. jadx 打开apk public boolean checkSN(String userName, String sn) { try { if (userName.length() == 0 && sn.length() == 0) { retu

【Android 逆向】【攻防世界】easy-dex

这一题不easy,不知为何叫这个名字。。。。 1. apk 安装到手机,不知所云,各种亮瞎眼闪光 2. jadx 打开apk,一行java代码都没有,打开AndroidManifest看看

【Android 逆向】【攻防世界】基础android

1. 下载并安装apk,提示要输入密码 2. apk拖入到jadx中看一下 this.login.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf02.MainActivity.1

【Android 逆向】【攻防世界】APK逆向

1. apk安装到手机,提示输入flag 2. jadx打开apk 定位到checkSN方法 public boolean checkSN(String userName, String sn) { if (userName != null) { try { if (userName.length(

【Android 逆向】【攻防世界】人民的名义-抓捕赵德汉1-200

1. 这一题下载下来是个jar文件,感觉很android关系不大,但还是放在了mobile这个分类下了 2. 直接java jar运行,提示需要输入密码 # java -jar 169e139f152e45d5ae634223fe53e6be.jar Enter password: 1234 Inc

【Android 逆向】【攻防世界】ill-intentions

1. apk 安装到手机, 啥输入框都没有 2. apk拖入到jadx中看看 public class MainActivity extends Activity { @Override // android.app.Activity public void onCreate(Bundle save

【Android 逆向】【攻防世界】boomshakalaka-3

1. apk 安装到手机,是一个cocos2dx 写的打飞机的游戏 题目描述跟得分有关(题目描述: play the game, get the highest score) 2. jadx 打开apk public class FirstTest extends Cocos2dxActivity

【Android 逆向】【攻防世界】easy-apk

apk 安装到手机,随便输入点内容,提示错误 2. apk 拖入到jadx中看看 public class MainActivity extends AppCompatActivity { /* JADX INFO: Access modifiers changed from: protected

【Android 逆向】【攻防世界】app1

1. apk安装到手机, 老套路了 2. jadx打开 this.btn.setOnClickListener(new View.OnClickListener() { // from class: com.example.yaphetshan.tencentgreat.MainActivity.1