-
-
[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第五题 丛林的秘密
-
发表于: 2019-6-18 15:31 3591
-
用JADX找到MainActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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返回的网址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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
1 2 3 4 5 | signed int JNI_OnLoad() { j_inti_proc(); return 65540; } |
只调用了一个j_inti_proc,
j_inti_proc里面又调用了inti_proc
1 2 3 4 5 | signed int JNI_OnLoad() { j_inti_proc(); return 65540; } |
只调用了一个j_inti_proc,
j_inti_proc里面又调用了inti_proc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 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处的数据导出解密一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 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实现。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
谁下载
谁下载
谁下载
赞赏
雪币:
留言: