-
-
[推荐]2019 KCTF 总决赛 | 第七题《东北奇闻》点评及解题思路
-
发表于: 2019-12-19 18:16 4804
-
1、题目简介
“老弟,你搁这儿干哈呢?坐这儿小心一会儿撞到你把波棱盖儿卡马路牙子上秃噜皮了。”“大姐我刚来还不认识路呢。”没想到这次居然来到了东北。好歹我也是六级的鸡米花了,对于系统的套路还是比较了解的,一般来跟我打招呼的都会是我这次任务的对象。“夜晚在外面不安全,麻利地跟大姐回家,吃顿热乎的饭。”看着眼前热情的大姐,我就跟她回家去了。原来大姐一家是卖豆花的,我端着一碗豆花对她家仔细打量起来。厅堂正中的桌子四四方方,上面摆着一个绿皮挂钟,墙上挂着一把鲜红的尺子,门上都贴着崭新的符纸,我仔细分辨一下上面似乎写着“与天同寿”。深夜,我在热乎乎的炕上被什么声音吵醒,门外传来一阵阵整齐的脚步声,挂钟响了十二下,我从窗口向外望去,来时的冷清的街道灯火辉煌,人声鼎沸,这些人在做些什么?难道是非法交易?房间里的符纸又是什么意思?不行,我得一探究竟。
[说明:本题是一道Android题]
接下来让我们一起来看一下这道题的点评和详细解析吧。
2、看雪评委crownless点评
这是一道jni题。so做了一些混淆,字符串加密可以干扰静态分析。这对选手破解赛题构成了挑战。
这道题主要考察了动态调试的能力和密码学算法的领悟能力。
3、出题团队简介
队长卓桐个人简介:野生Android程序员。
4、设计思路
分析流程
但是加了类似花指令的效果,对静态分析有些影响,对其进行一些修复,或者直接动态调试。
对其进行修复,可以查看伪代码:
JNI_OnLoad注册jni函数:
或者通过给出的提示,直接通过字符串定位到jni函数:
分析该jni函数主要获取用户输入的字符串,调用加密函数。
加密函数
首先设置一个16字节的key,然后进行25次加密,根据数组长度200和8得出,动态调试知道为分块加密,一块为8个字节,加密后也是8字节。
对加密后的字节格式化为hex形式的字符串,和预置的字符串比较,如果相同弹出字符串:
Correct flag = flag{…}
解密
用于比较的解密后的字符串为:
68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cfd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfcd9b426919547bcfc
从后往前观察发现16个字符为一组,后面的都是相同的字符串,得出d9b426919547bcfc为8个0加密后的值,所以其实需要解密的是:
68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf
明文应该为25-32个字节,格式为flag{}。
逆向加密代码:
分析并不需要逆向所有代码,比如有16字节的key得到32*4字节的key的过程就可以省略,直接动态调试得到。
最后加密后的8个字节,每个字节都会被一个函数改变,这个函数被人工混淆和使用工具混淆过了,其实根本不用去逆,因为传入一个字节得到一个字节,范围总共256,那么只需要遍历256次,通过hook等都可以,得到一个0-255的对应的表。
把68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf
查表替换得到fb4e45306acaeae7c2232d529720f743ae3097e269910fad56841548349ceccf
staticconst u32 sbox1[256] = {
0x01010400,0x00000000,0x00010000,0x01010404,
0x01010004,0x00010404,0x00000004,0x00010000,
0x00000400,0x01010400,0x01010404,0x00000400,
0x01000404,0x01010004,0x01000000,0x00000004,
0x00000404,0x01000400,0x01000400,0x00010400,
0x00010400,0x01010000,0x01010000,0x01000404,
0x00010004,0x01000004,0x01000004,0x00010004,
0x00000000,0x00000404,0x00010404,0x01000000,
0x00010000,0x01010404,0x00000004,0x01010000,
0x01010400,0x01000000,0x01000000,0x00000400,
0x01010004,0x00010000,0x00010400,0x01000004,
0x00000400,0x00000004,0x01000404,0x00010404,
0x01010404,0x00010004,0x01010000,0x01000404,
0x01000004,0x00000404,0x00010404,0x01010400,
0x00000404,0x01000400,0x01000400,0x00000000,
0x00010004,0x00010400,0x00000000,0x01010004,
0x80108020,0x80008000,0x00008000,0x00108020,
0x00100000,0x00000020,0x80100020,0x80008020,
0x80000020,0x80108020,0x80108000,0x80000000,
0x80008000,0x00100000,0x00000020,0x80100020,
0x00108000,0x00100020,0x80008020,0x00000000,
0x80000000,0x00008000,0x00108020,0x80100000,
0x00100020,0x80000020,0x00000000,0x00108000,
0x00008020,0x80108000,0x80100000,0x00008020,
0x00000000,0x00108020,0x80100020,0x00100000,
0x80008020,0x80100000,0x80108000,0x00008000,
0x80100000,0x80008000,0x00000020,0x80108020,
0x00108020,0x00000020,0x00008000,0x80000000,
0x00008020,0x80108000,0x00100000,0x80000020,
0x00100020,0x80008020,0x80000020,0x00100020,
0x00108000,0x00000000,0x80008000,0x00008020,
0x80000000,0x80100020,0x80108020,0x00108000,
0x00000208,0x08020200,0x00000000,0x08020008,
0x08000200,0x00000000,0x00020208,0x08000200,
0x00020008,0x08000008,0x08000008,0x00020000,
0x08020208,0x00020008,0x08020000,0x00000208,
0x08000000,0x00000008,0x08020200,0x00000200,
0x00020200,0x08020000,0x08020008,0x00020208,
0x08000208,0x00020200,0x00020000,0x08000208,
0x00000008,0x08020208,0x00000200,0x08000000,
0x08020200,0x08000000,0x00020008,0x00000208,
0x00020000,0x08020200,0x08000200,0x00000000,
0x00000200,0x00020008,0x08020208,0x08000200,
0x08000008,0x00000200,0x00000000,0x08020008,
0x08000208,0x00020000,0x08000000,0x08020208,
0x00000008,0x00020208,0x00020200,0x08000008,
0x08020000,0x08000208,0x00000208,0x08020000,
0x00020208,0x00000008,0x08020008,0x00020200,
0x00802001,0x00002081,0x00002081,0x00000080,
0x00802080,0x00800081,0x00800001,0x00002001,
0x00000000,0x00802000,0x00802000,0x00802081,
0x00000081,0x00000000,0x00800080,0x00800001,
0x00000001,0x00002000,0x00800000,0x00802001,
0x00000080,0x00800000,0x00002001,0x00002080,
0x00800081,0x00000001,0x00002080,0x00800080,
0x00002000,0x00802080,0x00802081,0x00000081,
0x00800080,0x00800001,0x00802000,0x00802081,
0x00000081,0x00000000,0x00000000,0x00802000,
0x00002080,0x00800080,0x00800081,0x00000001,
0x00802001,0x00002081,0x00002081,0x00000080,
0x00802081,0x00000081,0x00000001,0x00002000,
0x00800001,0x00002001,0x00802080,0x00800081,
0x00002001,0x00002080,0x00800000,0x00802001,
0x00000080,0x00800000,0x00002000,0x00802080
};
staticconst u32 sbox2[256] = {
0x00000100,0x02080100,0x02080000,0x42000100,
0x00080000,0x00000100,0x40000000,0x02080000,
0x40080100,0x00080000,0x02000100,0x40080100,
0x42000100,0x42080000,0x00080100,0x40000000,
0x02000000,0x40080000,0x40080000,0x00000000,
0x40000100,0x42080100,0x42080100,0x02000100,
0x42080000,0x40000100,0x00000000,0x42000000,
0x02080100,0x02000000,0x42000000,0x00080100,
0x00080000,0x42000100,0x00000100,0x02000000,
0x40000000,0x02080000,0x42000100,0x40080100,
0x02000100,0x40000000,0x42080000,0x02080100,
0x40080100,0x00000100,0x02000000,0x42080000,
0x42080100,0x00080100,0x42000000,0x42080100,
0x02080000,0x00000000,0x40080000,0x42000000,
0x00080100,0x02000100,0x40000100,0x00080000,
0x00000000,0x40080000,0x02080100,0x40000100,
0x20000010,0x20400000,0x00004000,0x20404010,
0x20400000,0x00000010,0x20404010,0x00400000,
0x20004000,0x00404010,0x00400000,0x20000010,
0x00400010,0x20004000,0x20000000,0x00004010,
0x00000000,0x00400010,0x20004010,0x00004000,
0x00404000,0x20004010,0x00000010,0x20400010,
0x20400010,0x00000000,0x00404010,0x20404000,
0x00004010,0x00404000,0x20404000,0x20000000,
0x20004000,0x00000010,0x20400010,0x00404000,
0x20404010,0x00400000,0x00004010,0x20000010,
0x00400000,0x20004000,0x20000000,0x00004010,
0x20000010,0x20404010,0x00404000,0x20400000,
0x00404010,0x20404000,0x00000000,0x20400010,
0x00000010,0x00004000,0x20400000,0x00404010,
0x00004000,0x00400010,0x20004010,0x00000000,
0x20404000,0x20000000,0x00400010,0x20004010,
0x00200000,0x04200002,0x04000802,0x00000000,
0x00000800,0x04000802,0x00200802,0x04200800,
0x04200802,0x00200000,0x00000000,0x04000002,
0x00000002,0x04000000,0x04200002,0x00000802,
0x04000800,0x00200802,0x00200002,0x04000800,
0x04000002,0x04200000,0x04200800,0x00200002,
0x04200000,0x00000800,0x00000802,0x04200802,
0x00200800,0x00000002,0x04000000,0x00200800,
0x04000000,0x00200800,0x00200000,0x04000802,
0x04000802,0x04200002,0x04200002,0x00000002,
0x00200002,0x04000000,0x04000800,0x00200000,
0x04200800,0x00000802,0x00200802,0x04200800,
0x00000802,0x04000002,0x04200802,0x04200000,
0x00200800,0x00000000,0x00000002,0x04200802,
0x00000000,0x00200802,0x04200000,0x00000800,
0x04000002,0x04000800,0x00000800,0x00200002,
0x10001040,0x00001000,0x00040000,0x10041040,
0x10000000,0x10001040,0x00000040,0x10000000,
0x00040040,0x10040000,0x10041040,0x00041000,
0x10041000,0x00041040,0x00001000,0x00000040,
0x10040000,0x10000040,0x10001000,0x00001040,
0x00041000,0x00040040,0x10040040,0x10041000,
0x00001040,0x00000000,0x00000000,0x10040040,
0x10000040,0x10001000,0x00041040,0x00040000,
0x00041040,0x00040000,0x10041000,0x00001000,
0x00000040,0x10040040,0x00001000,0x00041040,
0x10001000,0x00000040,0x10000040,0x10040000,
0x10040040,0x10000000,0x00040000,0x10001040,
0x00000000,0x10041040,0x00040040,0x10000040,
0x10040000,0x10001000,0x10001040,0x00000000,
0x10041040,0x00041000,0x00041000,0x00001040,
0x00001040,0x00040040,0x10000000,0x10041000
};
staticconst u32 sbox3[256] = {
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
};
staticconst u32 sbox4[256] = {
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
};
u32 xkey[32] = {
0xd573f1e4,0xfa05e8a8,0x2c6d872d,0xc193bc8f,
0x18c94337,0x64bc5c3a,0x8f4696c2,0x384c937c,
0xb658582a,0x78f874ca,0x258bf885,0x6d208f8a,
0x5cd503d7,0xd4fa1e37,0x93dd1be,0x507f2a3e,
0x10,0x11,0x6,0xa,
0x16,0x1d,0x1a,0x13,
0xb,0x3,0x1c,0x0,
0x1d,0x10,0x19,0x1b,
};
#define U8a(x) ( (u8) (x>>24) )
#define U8b(x) ( (u8) (((x)>>16)&255) )
#define U8c(x) ( (u8) (((x)>>8)&255) )
#define U8d(x) ( (u8) ((x)&255) )
#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) )
#define F1(l, r, i) \
t = ROL(key[i] + r, key[i+16]); \
l ^= ((sbox1[U8a(t)] ^ sbox2[U8b(t)]) \
- sbox3[U8c(t)]) + sbox4[U8d(t)];
#define F2(l, r, i) \
t = ROL(key[i] ^ r, key[i+16]); \
l ^= ((sbox1[U8a(t)] - sbox2[U8b(t)]) \
+ sbox3[U8c(t)]) ^ sbox4[U8d(t)];
#define F3(l, r, i) \
t = ROL(key[i] - r, key[i+16]); \
l ^= ((sbox1[U8a(t)] + sbox2[U8b(t)]) \
^ sbox3[U8c(t)]) - sbox4[U8d(t)];
void mcrypt_decrypt(u32 *key, u8 * block)
{
u32 t, l, r;
r = ((u32) block[0] <<24) | ((u32) block[1] <<16)
| ((u32) block[2] <<8) | (u32) block[3];
l = ((u32) block[4] <<24) | ((u32) block[5] <<16)
| ((u32) block[6] <<8) | (u32) block[7];
// v9 = __ROR4__(*v3 + v8, 32 - v3[16]);
// v10 = v6 ^ ((dword_2A410[(v9 >> 16) & 0xFF] ^ dword_2A010[v9 >> 24])
// - dword_2A810[(unsigned __int16)v9 >> 8]
// + dword_2AC10[(unsigned __int8)v9]);
// v11 = __ROR4__(v10 ^ v3[1], 32 - v3[17]);
F3(r, l,11);
F2(l, r,10);
F1(r, l,9);
F3(l, r,8);
F2(r, l,7);
F1(l, r,6);
F3(r, l,5);
F2(l, r,4);
F1(r, l,3);
F3(l, r,2);
F2(r, l,1);
F1(l, r,0);
block[0] = U8a(l);
block[1] = U8b(l);
block[2] = U8c(l);
block[3] = U8d(l);
block[4] = U8a(r);
block[5] = U8b(r);
block[6] = U8c(r);
block[7] = U8d(r);
t = l = r =0;
}
static void Hex2Char(const char *szHex, unsigned char *rch)
{
int i;
for(i=0; i<2; i++)
{
if(*(szHex + i) >='0' && *(szHex + i) <='9')
*rch = (*rch <<4) + (*(szHex + i) -'0');
else if(*(szHex + i) >='a' && *(szHex + i) <='f')
*rch = (*rch <<4) + (*(szHex + i) -'a' +10);
else
break;
}
}
void HexStr2CharStr(const char *pszHexStr,int iSize, unsigned char *pucCharStr)
{
int i;
unsigned char ch;
if (iSize%2 !=0)return;
for(i=0; i<iSize/2; i++)
{
Hex2Char(pszHexStr+2*i, &ch);
pucCharStr[i] = ch;
}
}
int main(){
int blocksize =8, j;
const char *code ="68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf";
code ="fb4e45306acaeae7c2232d529720f743ae3097e269910fad56841548349ceccf";
size_tlen = strlen(code) /2;
u8 *encode = static_cast<u8 *>(malloc(len+1));
HexStr2CharStr(code, strlen(code), encode);
for (int i =0; i <4; ++i) {
mcrypt_decrypt(xkey, (u8 *) encode + i * blocksize);
}
encode[len] =0;
printf("%s == %s\n", encode, code);
return 0;
}
得到flag:flag{9eca5de49470144c1694f6}
5、解题思路
本题解题思路由打打酱油战队 梦游枪手 提供:
用jadx查看apk,找到MainActivity。
public class MainActivity extends AppC0mpatActivity {
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
setContentView((int) R.layout.activity_main);
final EditText editText = (EditText) findViewById(R.id.ed);
((Button) findViewById(R.id.bt)).setOnClickListener(new OnClickListener() {
public void onClick(View view) {
if (editText.getText() ==null || TextUtils.isEmpty(editText.getText().toString()) !=null || MainActivity.this.showAssist(bundle) !=null) {
Toast.makeText(MainActivity.this,"null",1).show();
}
}
});
}
}
so做了一些混淆以及字符串加密,干扰静态分析。
但没有反调试,可以真机调试找出showAssist的地址。
我是选择用frida hook RegisterNatives函数,输出showAssist的地址。
在00019F80处下断,运行程序输入flag就能停下了。
大致流程为,申请200字节大小的空间,将输入的flag写到那个空间 ,每8字节一组加密。再与内置的结果比较。
后面都是0加密的结果,也就是说flag加密后与"68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf"相同则通过。
直接抠加密函数sub_9CB0代码,将下面的混淆代码nop掉就能F5了。
部分伪代码如下:
v7 =__ROR4__(*encrypt + flag4, 32 - encrypt[16]);
v8 = flag0 ^ ((des2[(v7 >> 16) & 0xFF] ^ des1[v7 >> 24]) - S[(unsigned__int16)v7 >> 8] + S2[(unsigned __int8)v7]);
v9 =__ROR4__(v8 ^ encrypt[1], 32 - encrypt[17]);
v10 = (des1[v9 >> 24] - des2[(v9 >> 16) & 0xFF] + S[(unsigned__int16)v9 >> 8]) ^ flag4 ^ S2[(unsigned __int8)v9];
v11 =__ROR4__(encrypt[2] - v10, 32 - encrypt[18]);
v12 = (((des2[(v11 >> 16) & 0xFF] + des1[v11 >> 24]) ^ S[(unsigned__int16)v11 >> 8]) - S2[(unsigned __int8)v11]) ^ v8;
v13 =__ROR4__(v12 + encrypt[3], 32 - encrypt[19]);
v14 = (S2[(unsigned__int8)v13] + (des2[(v13 >> 16) & 0xFF] ^ des1[v13 >> 24]) - S[(unsigned __int16)v13 >> 8]) ^ v10;
v15 =__ROR4__(encrypt[4] ^ v14, 32 - encrypt[20]);
v16 = S2[(unsigned__int8)v15] ^ v12 ^ (des1[v15 >> 24] - des2[(v15 >> 16) & 0xFF] + S[(unsigned __int16)v15 >> 8]);
v17 =__ROR4__(encrypt[5] - v16, 32 - encrypt[21]);
v18 = v14 ^ (((des1[v17 >> 24] + des2[(v17 >> 16) & 0xFF]) ^ S[(unsigned__int16)v17 >> 8]) - S2[(unsigned __int8)v17]);
v19 =__ROR4__(encrypt[6] + v18, 32 - encrypt[22]);
v20 = v16 ^ ((des2[(v19 >> 16) & 0xFF] ^ des1[v19 >> 24]) - S[(unsigned__int16)v19 >> 8] + S2[(unsigned __int8)v19]);
v21 =__ROR4__(encrypt[7] ^ v20, 32 - encrypt[23]);
v22 = S2[(unsigned__int8)v21] ^ v18 ^ (des1[v21 >> 24] - des2[(v21 >> 16) & 0xFF] + S[(unsigned __int16)v21 >> 8]);
v23 =__ROR4__(encrypt[8] - v22, 32 - encrypt[24]);
v24 = v20 ^ (((des2[(v23 >> 16) & 0xFF] + des1[v23 >> 24]) ^ S[(unsigned__int16)v23 >> 8]) - S2[(unsigned __int8)v23]);
v25 =__ROR4__(encrypt[9] + v24, 32 - encrypt[25]);
v26 = v22 ^ ((des1[v25 >> 24] ^ des2[(v25 >> 16) & 0xFF]) - S[(unsigned__int16)v25 >> 8] + S2[(unsigned __int8)v25]);
v27 =__ROR4__(encrypt[10] ^ v26, 32 - encrypt[26]);
v28 = (des1[v27 >> 24] - des2[(v27 >> 16) & 0xFF] + S[(unsigned__int16)v27 >> 8]) ^ S2[(unsigned __int8)v27] ^ v24;
v29 =__ROR4__(encrypt[11] - v28, 32 -*((_BYTE *)encrypt + 0x6C));
v30 = ((S[(unsigned__int16)v29 >> 8] ^ (des1[v29 >> 24] + des2[(v29 >> 16) & 0xFF])) - S2[(unsigned __int8)v29]) ^ v26;
*(_BYTE *)result = sub_DF18(v30 >> 24);
*((_BYTE *)result + 1) = sub_DF18((v30 >> 16) & 0xFF);
*((_BYTE *)result + 2) = sub_DF18((unsigned __int16)v30 >> 8);
*((_BYTE *)result + 3) = sub_DF18((unsigned __int8)v30);
*((_BYTE *)result + 4) = sub_DF18(v28 >> 24);
*((_BYTE *)result + 5) = sub_DF18((v28 >> 16) & 0xFF);
*((_BYTE *)result + 6) = sub_DF18((unsigned __int16)v28 >> 8);
*((_BYTE *)result + 7) = sub_DF18((unsigned __int8)v28);
sub_DF18函数里面有更强的混淆,但是动态调试时发现只是一个字节变换,可以写个脚本抠出[0,255]的变换结果,然后写代码输出解密用的表。
加密部分的代码看起来有点乱,但是仔细钻研了下,发现其实是花式xor。返回的加密结果其实就是v28和v30,已知v28和v30可以求出v29,之后用v26 = ((S[(unsigned __int16)v29 >> 8] ^ (des1[v29 >> 24] + des2[(v29 >> 16) & 0xFF])) - S2[(unsigned __int8)v29]) ^ v30;
求出v26的值,以此类推,就能还原出flag了。
其他的表可以直接导出,弄一份可编译的C代码,完整代码见附件。
int decryptstring(unsigned char* buffer)
{
int v2;// r10
unsigned int *v3;// ST00_4
unsigned int v4;// r5
unsigned int v5;// r11
unsigned int v6;// r8
unsigned int v7;// r2
int v8;// r11
unsigned int v9;// r4
int v10;// r8
unsigned int v11;// r5
int v12;// lr
unsigned int v13;// r6
int v14;// r12
unsigned int v15;// r5
int v16;// lr
unsigned int v17;// r6
int v18;// r12
unsigned int v19;// r6
int v20;// lr
unsigned int v21;// r5
int v22;// r12
unsigned int v23;// r6
int v24;// lr
unsigned int v25;// r6
int v26;// r12
unsigned int v27;// r5
unsigned int v28;// r4
unsigned int v29;// r5
unsigned int v30;// r6
unsigned int result1;
unsigned int result2;
unsigned int flag0;
unsigned int flag4;
unsigned char enc[9]={0};
for (int i =0; i <4; ++i)
{
enc[i]=ctable2[buffer[i]];
enc[4+i]=ctable2[buffer[4+i]];
}
result1 = (enc[0]<<24)+(enc[1]<<16)+(enc[2]<<8)+enc[3];
result2 = (enc[4]<<24)+(enc[5]<<16)+(enc[6]<<8)+enc[7];
v30 = result1;
v28 = result2;
v29 = ror(encrypt[11] - v28,32 - *((unsigned char *)encrypt +0x6C));
v26 = v30 ^ ((S[(unsigned short)v29 >>8] ^ (des1[v29 >>24] + des2[(v29 >>16) &0xFF])) - S2[(unsigned char)v29]);
v27 = ror(encrypt[10] ^ v26,32 - encrypt[26]);
v24 = v28 ^ (des1[v27 >>24] - des2[(v27 >>16) &0xFF] + S[(unsigned short)v27 >>8]) ^ S2[(unsigned char)v27];
v25 = ror(encrypt[9] + v24,32 - encrypt[25]);
v22 = v26 ^ ((des1[v25 >>24] ^ des2[(v25 >>16) &0xFF]) - S[(unsigned short)v25 >>8] + S2[(unsigned char)v25]);
v23 = ror(encrypt[8] - v22,32 - encrypt[24]);
v20 = v24 ^ (((des2[(v23 >>16) &0xFF] + des1[v23 >>24]) ^ S[(unsigned short)v23 >>8]) - S2[(unsigned char)v23]);
v21 = ror(encrypt[7] ^ v20,32 - encrypt[23]);
v18 = v22 ^ S2[(unsigned char)v21] ^ (des1[v21 >>24] - des2[(v21 >>16) &0xFF] + S[(unsigned short)v21 >>8]);
v19 = ror(encrypt[6] + v18,32 - encrypt[22]);
v16 = v20 ^ ((des2[(v19 >>16) &0xFF] ^ des1[v19 >>24]) - S[(unsigned short)v19 >>8] + S2[(unsigned char)v19]);
v17 = ror(encrypt[5] - v16,32 - encrypt[21]);
v14 = v18 ^ (((des1[v17 >>24] + des2[(v17 >>16) &0xFF]) ^ S[(unsigned short)v17 >>8]) - S2[(unsigned char)v17]);
v15 = ror(encrypt[4] ^ v14,32 - encrypt[20]);
v12 = v16 ^ S2[(unsigned char)v15] ^ (des1[v15 >>24] - des2[(v15 >>16) &0xFF] + S[(unsigned short)v15 >>8]);
v13 = ror(v12 + encrypt[3],32 - encrypt[19]);
v10 = v14 ^ (S2[(unsigned char)v13] + (des2[(v13 >>16) &0xFF] ^ des1[v13 >>24]) - S[(unsigned short)v13 >>8]);
v11 = ror(encrypt[2] - v10,32 - encrypt[18]);
v8 = v12 ^ (((des2[(v11 >>16) &0xFF] + des1[v11 >>24]) ^ S[(unsigned short)v11 >>8]) - S2[(unsigned char)v11]);
v9 = ror(v8 ^ encrypt[1],32 - encrypt[17]);
flag4 = v10 ^ (des1[v9 >>24] - des2[(v9 >>16) &0xFF] + S[(unsigned short)v9 >>8]) ^ S2[(unsigned char)v9];
v7 = ror(*encrypt + flag4,32 - encrypt[16]);
flag0 = v8 ^ ((des2[(v7 >>16) &0xFF] ^ des1[v7 >>24]) - S[(unsigned short)v7 >>8] + S2[(unsigned char)v7]);
for (int i =0; i <4; ++i)
{
enc[i]=(flag0>>((3-i)*8))&0xff;
enc[4+i]=(flag4>>((3-i)*8))&0xff;
}
printf("%s",enc);
return 0;
}
int main(int argc,char const *argv[])
{
unsigned char buffer[9]={0};
//"68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf"
unsigned char str1[8]={0x68,0xdd,0x8a,0x0f,0x70,0x65,0x60,0x9e};
unsigned char str2[8]={0x31,0x06,0xfb,0x2b,0xb1,0x05,0x94,0x23};
unsigned char str3[8]={0xe8,0x0f,0xb1,0x34,0x73,0x18,0xff,0xeb};
unsigned char str4[8]={0x83,0xb8,0xa0,0x74,0xa7,0xe6,0xc9,0xcf};
decryptstring(str1);
decryptstring(str2);
decryptstring(str3);
decryptstring(str4);
printf("\n");
return 0;
}
将"68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf"拆成四组分别解密就得到flag了。
flag:flag{9eca5de49470144c1694f6}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!