首页
社区
课程
招聘
[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第五题 丛林的秘密
发表于: 2019-6-18 15:31 3414

[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第五题 丛林的秘密

2019-6-18 15:31
3414

用JADX找到MainActivity

public class MainActivity extends AppCompatActivity {
    private Button button1;
    private EditText eText1;
    private TextView txView1;
    public String u = gogogoJNI.sayHello();

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

    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView((int) R.layout.activity_main);
        this.eText1 = (EditText) findViewById(R.id.editText);
        this.txView1 = (TextView) findViewById(R.id.textView);
        ((WebView) findViewById(R.id.text1View)).loadUrl(this.u);
        ((WebView) findViewById(R.id.text1View)).getSettings().setJavaScriptEnabled(true);
        this.button1 = (Button) findViewById(R.id.button);
        this.button1.setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                if (gogogoJNI.check_key(MainActivity.this.eText1.getText().toString()) == 1) {
                    MainActivity.this.txView1.setText("Congratulations!");
                } else {
                    MainActivity.this.txView1.setText("Not Correct!");
                }
            }
        });
    }
}
看起来是调用了gogogo文件里的check_key函数,但是上面出现了一个很可疑的东西:WebView,并且加载sayHello返回的网址。
public class MainActivity extends AppCompatActivity {
    private Button button1;
    private EditText eText1;
    private TextView txView1;
    public String u = gogogoJNI.sayHello();

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

    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView((int) R.layout.activity_main);
        this.eText1 = (EditText) findViewById(R.id.editText);
        this.txView1 = (TextView) findViewById(R.id.textView);
        ((WebView) findViewById(R.id.text1View)).loadUrl(this.u);
        ((WebView) findViewById(R.id.text1View)).getSettings().setJavaScriptEnabled(true);
        this.button1 = (Button) findViewById(R.id.button);
        this.button1.setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                if (gogogoJNI.check_key(MainActivity.this.eText1.getText().toString()) == 1) {
                    MainActivity.this.txView1.setText("Congratulations!");
                } else {
                    MainActivity.this.txView1.setText("Not Correct!");
                }
            }
        });
    }
}
看起来是调用了gogogo文件里的check_key函数,但是上面出现了一个很可疑的东西:WebView,并且加载sayHello返回的网址。
那我们用IDA打开 libgogogo.so
先看Java_com_example_assemgogogo_gogogoJNI_sayHello函数
int __fastcall Java_com_example_assemgogogo_gogogoJNI_sayHello(JNIEnv *a1)
{
  int v1; // r11
  JNIEnv *v2; // r4
  int i; // r0
  int v5; // [sp+0h] [bp-98h]
  char v6; // [sp+15h] [bp-83h]
  int v7; // [sp+88h] [bp-10h]

  v7 = v1;
  v2 = a1;
  _aeabi_memclr8(&v5, 128);
  for ( i = 0; i != 21; ++i )
    *((_BYTE *)&v5 + i) = byte_2D28[i] ^ 0x66;  // 异或解密,结果是http://127.0.0.1:8000
  v6 = 0;
  return ((int (__fastcall *)(JNIEnv *, int *))(*v2)->NewStringUTF)(v2, &v5);
}
那 MainActivity加载的就是本机的8000端口。但是在dex文件没发现类似网页的内容,我们继续分析so文件
int __fastcall Java_com_example_assemgogogo_gogogoJNI_sayHello(JNIEnv *a1)
{
  int v1; // r11
  JNIEnv *v2; // r4
  int i; // r0
  int v5; // [sp+0h] [bp-98h]
  char v6; // [sp+15h] [bp-83h]
  int v7; // [sp+88h] [bp-10h]

  v7 = v1;
  v2 = a1;
  _aeabi_memclr8(&v5, 128);
  for ( i = 0; i != 21; ++i )
    *((_BYTE *)&v5 + i) = byte_2D28[i] ^ 0x66;  // 异或解密,结果是http://127.0.0.1:8000
  v6 = 0;
  return ((int (__fastcall *)(JNIEnv *, int *))(*v2)->NewStringUTF)(v2, &v5);
}
那 MainActivity加载的就是本机的8000端口。但是在dex文件没发现类似网页的内容,我们继续分析so文件
先看JNI_OnLoad
signed int JNI_OnLoad()
{
  j_inti_proc();
  return 65540;
}
只调用了一个j_inti_proc, j_inti_proc里面又调用了inti_proc
signed int JNI_OnLoad()
{
  j_inti_proc();
  return 65540;
}
只调用了一个j_inti_proc, j_inti_proc里面又调用了inti_proc
int inti_proc()
{
  char *v0; // r0
  signed int v1; // r1
  signed int i; // r6
  struct addrinfo **v3; // r0
  int v4; // r4
  struct addrinfo *v5; // r5
  int result; // r0
  int arg; // [sp+8h] [bp-70h]
  int v8; // [sp+Ch] [bp-6Ch]
  int v9; // [sp+10h] [bp-68h]
  struct addrinfo *pai; // [sp+14h] [bp-64h]
  struct addrinfo req; // [sp+18h] [bp-60h]
  char v12[32]; // [sp+38h] [bp-40h]
  int v13; // [sp+58h] [bp-20h]

  v0 = &mm0;
  v1 = 34291;
  v9 = 1;
  while ( v1 )
  {
    --v1;
    *v0 ^= 0x67u;
    ++v0;
  }
  i = 1;
  *(_QWORD *)&req.ai_protocol = 0LL;
  *(_QWORD *)&req.ai_addr = 0LL;
  req.ai_family = 0;
  req.ai_flags = 1;
  req.ai_socktype = 1;
  req.ai_next = 0;
  if ( getaddrinfo(0, "8000", &req, &pai) )
    goto LABEL_19;
  v3 = &pai;
  i = 1;
  while ( 1 )
  {
    v5 = *v3;
    if ( !*v3 )
    {
      i = 2;
      goto LABEL_19;
    }
    v4 = socket(v5->ai_family, v5->ai_socktype, v5->ai_protocol);
    if ( v4 != -1 )
      break;
LABEL_10:
    v3 = &v5->ai_next;
  }
  if ( setsockopt(v4, 1, 2, &v9, 4u) == -1 )
    goto LABEL_19;
  if ( bind(v4, (const struct sockaddr *)v5->ai_canonname, v5->ai_addrlen) == -1 )
  {
    close(v4);
    goto LABEL_10;
  }
  freeaddrinfo(pai);
  if ( listen(v4, 128) == -1 )
  {
    i = 1;
  }
  else
  {
    for ( i = 0; i != 32; i += 4 )
    {
      arg = v4;
      v8 = 0;
      pthread_create((pthread_t *)&v12[i], 0, (void *(*)(void *))nullsub_, &arg);
    }
    sock_fd_g = v4;
  }
LABEL_19:
  result = _stack_chk_guard - v13;
  if ( _stack_chk_guard == v13 )
    result = i;
  return result;
}
发现了初始化socket的代码,而且也是监视8000端口。代码一开始貌似在解密什么,尝试把mm0处的数据导出解密一下
int inti_proc()
{
  char *v0; // r0
  signed int v1; // r1
  signed int i; // r6
  struct addrinfo **v3; // r0
  int v4; // r4
  struct addrinfo *v5; // r5
  int result; // r0
  int arg; // [sp+8h] [bp-70h]
  int v8; // [sp+Ch] [bp-6Ch]
  int v9; // [sp+10h] [bp-68h]
  struct addrinfo *pai; // [sp+14h] [bp-64h]
  struct addrinfo req; // [sp+18h] [bp-60h]
  char v12[32]; // [sp+38h] [bp-40h]
  int v13; // [sp+58h] [bp-20h]

  v0 = &mm0;
  v1 = 34291;
  v9 = 1;
  while ( v1 )
  {
    --v1;
    *v0 ^= 0x67u;
    ++v0;
  }
  i = 1;
  *(_QWORD *)&req.ai_protocol = 0LL;
  *(_QWORD *)&req.ai_addr = 0LL;
  req.ai_family = 0;
  req.ai_flags = 1;
  req.ai_socktype = 1;
  req.ai_next = 0;
  if ( getaddrinfo(0, "8000", &req, &pai) )
    goto LABEL_19;
  v3 = &pai;
  i = 1;
  while ( 1 )
  {
    v5 = *v3;
    if ( !*v3 )
    {
      i = 2;
      goto LABEL_19;
    }
    v4 = socket(v5->ai_family, v5->ai_socktype, v5->ai_protocol);
    if ( v4 != -1 )
      break;
LABEL_10:
    v3 = &v5->ai_next;
  }
  if ( setsockopt(v4, 1, 2, &v9, 4u) == -1 )
    goto LABEL_19;
  if ( bind(v4, (const struct sockaddr *)v5->ai_canonname, v5->ai_addrlen) == -1 )
  {
    close(v4);
    goto LABEL_10;
  }
  freeaddrinfo(pai);
  if ( listen(v4, 128) == -1 )
  {
    i = 1;
  }
  else
  {
    for ( i = 0; i != 32; i += 4 )
    {
      arg = v4;
      v8 = 0;
      pthread_create((pthread_t *)&v12[i], 0, (void *(*)(void *))nullsub_, &arg);
    }
    sock_fd_g = v4;
  }
LABEL_19:
  result = _stack_chk_guard - v13;
  if ( _stack_chk_guard == v13 )
    result = i;
  return result;
}
发现了初始化socket的代码,而且也是监视8000端口。代码一开始貌似在解密什么,尝试把mm0处的数据导出解密一下

我们要找的html就在这, 由于完整html代码太长,我就放在附件吧。 
保存到html文件里面后,用chrome调试。JS代码调用了check_key来检查key, 而check_key这个函数在WebAssembly实现。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//