首页
社区
课程
招聘
看雪CTF2019Q1-第2题
2019-3-18 21:38 2998

看雪CTF2019Q1-第2题

2019-3-18 21:38
2998
1. apk
 so里判断密码是否正确, 正确则解密flag, 需要提交的是密码, 因此直接看so
package com.zhuotong.crackme;
public class MainActivity extends AppCompiatActivity;

package android.support.v7.app;
public class AppCompiatActivity extends AppCompatActivity {
    static {
        System.loadLibrary("oo000oo");
    }
    protected native boolean eq(String arg1);
    protected void onStart() {
				...
        this.login.setOnClickListener(new View$OnClickListener() {
            public void onClick(View arg5) {
            						...
                        if(AppCompiatActivity.this.eq(AppCompiatActivity.this.mPassword)) {
                            byte[] v5 = AppCompiatActivity.this.mPassword.getBytes();
                            int v3 = 24;
                            if(v5.length != v3) {
                                byte[] v2 = new byte[v3];
                                while(v1 < v2.length) {
                                    byte v3_1 = v1 < v5.length ? v5[v1] : ((byte)v1);
                                    v2[v1] = v3_1;
                                    ++v1;
                                }

                                v5 = v2;
                            }
                            v5 = AppCompiatActivity.dec(v5, "2ggdrsLgM7iPNYPQrD58Rg==".getBytes());
                            AppCompiatActivity v1_1 = AppCompiatActivity.this;
                            StringBuilder v2_1 = new StringBuilder();
                            v2_1.append("flag{");
                            v2_1.append(new String(v5));
                            v2_1.append("}");
                            Toast.makeText(((Context)v1_1), v2_1.toString(), 1).show();
                        }
                        ...
            }
        });
        this.name = this.findViewById(2131165265);
        this.name.setEnabled(false);
        this.password = this.findViewById(2131165277);
    } 	
}

2. liboo000oo.so
解密用到的字符串
.init_array:00003E78                 DCD .datadiv_decode5009363700628197108+1

注册native函数android.support.v7.app.AppCompiatActivity.eq
int __fastcall JNI_OnLoad(JavaVM *a1)
{
  env = 0;
  if ( !(*a1)->GetEnv(a1, &env, 65540) )
    goto LABEL_4;
LABEL_2:
  result = -1;
  while ( _stack_chk_guard != v5 )
  {
LABEL_4:
    v2 = env;
    v3 = (*env)->FindClass(env, off_4010);
    dword_4110 = (*v2)->NewGlobalRef(v2, v3);
    if ( !v3 || (*v2)->RegisterNatives(v2, v3, &stru_4014, 1) <= -1 )
      goto LABEL_2;
    result = 65542;
  }
  return result;
}

.data:00004014 stru_4014       JNINativeMethod <aEq, aLjavaLangStrin, x_eq+1>

x_eq函数功能

字符串: 650f909c-7217-3647-9331-c82df8b98e98
去掉字符'-': 650f909c721736479331c82df8b98e98
逆序转换成GUID形式: 89e89b8f-d28c-1339-7463-7127c909f056
字符映射012345678abcdef -> 2409715836dbeafc: 36f36b3c-a03e-4996-8759-8408e626c215
得到的字符串为rc4的key

base64表: !:#$%&()+-*/`~_[]{}?<>,.@^abcdefghijklmnopqrstuvwxyz0123456789\';
base64_encode(rc4_crypt(key, password))
得到的字符串, 4位一组, 偶数位分别异或 0x07 和 0x0F, 
最终结果与目标串比较:  {9*8ga*l!Tn?@#fj'j$\g;; 

struct RC4_CONTEXT
{
	BYTE state[256];
	BYTE x;
	BYTE y;
}; 

void swap_item(PBYTE buf, BYTE i, BYTE j)
{
	BYTE t = buf[i];
	buf[i] = buf[j];
	buf[j] = t;
}

void custom_rc4_init(RC4_CONTEXT *ctx, PBYTE key, size_t key_len)
{
	BYTE state[256] = {
		0xD7, 0xDF, 0x02, 0xD4, 0xFE, 0x6F, 0x53, 0x3C, 0x25, 0x6C, 0x99, 0x97, 0x06, 0x56, 0x8F, 0xDE, 
		0x40, 0x11, 0x64, 0x07, 0x36, 0x15, 0x70, 0xCA, 0x18, 0x17, 0x7D, 0x6A, 0xDB, 0x13, 0x30, 0x37, 
		0x29, 0x60, 0xE1, 0x23, 0x28, 0x8A, 0x50, 0x8C, 0xAC, 0x2F, 0x88, 0x20, 0x27, 0x0F, 0x7C, 0x52, 
		0xA2, 0xAB, 0xFC, 0xA1, 0xCC, 0x21, 0x14, 0x1F, 0xC2, 0xB2, 0x8B, 0x2C, 0xB0, 0x3A, 0x66, 0x46, 
		0x3D, 0xBB, 0x42, 0xA5, 0x0C, 0x75, 0x22, 0xD8, 0xC3, 0x76, 0x1E, 0x83, 0x74, 0xF0, 0xF6, 0x1C, 
		0x26, 0xD1, 0x4F, 0x0B, 0xFF, 0x4C, 0x4D, 0xC1, 0x87, 0x03, 0x5A, 0xEE, 0xA4, 0x5D, 0x9E, 0xF4, 
		0xC8, 0x0D, 0x62, 0x63, 0x3E, 0x44, 0x7B, 0xA3, 0x68, 0x32, 0x1B, 0xAA, 0x2D, 0x05, 0xF3, 0xF7, 
		0x16, 0x61, 0x94, 0xE0, 0xD0, 0xD3, 0x98, 0x69, 0x78, 0xE9, 0x0A, 0x65, 0x91, 0x8E, 0x35, 0x85, 
		0x7A, 0x51, 0x86, 0x10, 0x3F, 0x7F, 0x82, 0xDD, 0xB5, 0x1A, 0x95, 0xE7, 0x43, 0xFD, 0x9B, 0x24, 
		0x45, 0xEF, 0x92, 0x5C, 0xE4, 0x96, 0xA9, 0x9C, 0x55, 0x89, 0x9A, 0xEA, 0xF9, 0x90, 0x5F, 0xB8, 
		0x04, 0x84, 0xCF, 0x67, 0x93, 0x00, 0xA6, 0x39, 0xA8, 0x4E, 0x59, 0x31, 0x6B, 0xAD, 0x5E, 0x5B, 
		0x77, 0xB1, 0x54, 0xDC, 0x38, 0x41, 0xB6, 0x47, 0x9F, 0x73, 0xBA, 0xF8, 0xAE, 0xC4, 0xBE, 0x34, 
		0x01, 0x4B, 0x2A, 0x8D, 0xBD, 0xC5, 0xC6, 0xE8, 0xAF, 0xC9, 0xF5, 0xCB, 0xFB, 0xCD, 0x79, 0xCE, 
		0x12, 0x71, 0xD2, 0xFA, 0x09, 0xD5, 0xBC, 0x58, 0x19, 0x80, 0xDA, 0x49, 0x1D, 0xE6, 0x2E, 0xE3, 
		0x7E, 0xB7, 0x3B, 0xB3, 0xA0, 0xB9, 0xE5, 0x57, 0x6E, 0xD9, 0x08, 0xEB, 0xC7, 0xED, 0x81, 0xF1, 
		0xF2, 0xBF, 0xC0, 0xA7, 0x4A, 0xD6, 0x2B, 0xB4, 0x72, 0x9D, 0x0E, 0x6D, 0xEC, 0x48, 0xE2, 0x33
	};
	CopyMemory(ctx->state, state, 256);

	size_t i = 0;
	size_t j = 0;
	size_t k = 0;
	for(i = 0; i < 256; i++)
	{
		j += ctx->state[i] + key[k++ % key_len];
		swap_item(ctx->state, i, j);
	}
	ctx->x = 0;
	ctx->y = 0;
}

void rc4_crypt(RC4_CONTEXT *ctx, PBYTE data, size_t data_len)
{ 
	BYTE x = ctx->x;
	BYTE y = ctx->y;
	PBYTE state = ctx->state;
	for(size_t i = 0; i < data_len; i++)
	{
		x += 1;
		y += state[x];
		swap_item(state, x, y);
		data[i] ^= state[(BYTE)(state[x] + state[y])];
	}
	ctx->x = x;
	ctx->y = y;
}

void test1()
{
	char buf[24+1] = " {9*8ga*l!Tn?@#fj'j$\\g;;";
	for (int i = 0; i < 24; i++)
	{
		if ((i % 4) == 0)
		{
			buf[i] ^= 0x07;
		}
		if ((i % 4) == 2)
		{
			buf[i] ^= 0x0F;
		}
	}
	printf("%s\n", buf);
}

void test2()
{
	const char *key = "36f36b3c-a03e-4996-8759-8408e626c215";
	size_t key_len = strlen(key);
	
	RC4_CONTEXT ctx;
	custom_rc4_init(&ctx, (PBYTE)key, key_len);

	string data = util::hex2bin("FD1E8A4E09CA9003E7F1859F9BF7833E");
	PBYTE buf = (PBYTE)data.c_str();
	rc4_crypt(&ctx, buf, data.size());
	print_str(buf, data.size());
}

得到密码: fu0kzHp2aqtZAuY6

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回