-
-
[原创]lcweik的第一第二题writeup
-
发表于: 2015-10-21 04:55 16485
-
第一题write up
拿到题目,首先是反编译和dex2jar
在jad-gui里看不到关键类check的java源码,
然后在smali代码基础上,去掉所有的synthetic字段,并把所以有的.catch替换为#.catch,
再重新生成dex文件,就可以在jad-gui里看到check类的java源码。
在jad-gui中看代码时,发现,它还做了混淆,有大量的数组赋值语句及反射调用,无法阅读,
但可以看到代码结构基本上是线性的,所以,只要盯着保存有用户输入的密码的那几个寄存器及if语句下断点,就能跟踪到关键逻辑。
关键逻辑有三个:
1、将用户输入数据转化为数字num1,所以密码一定是数字
2、将num1与1 5 9 ... 1001相加,但在下一步比较中发现是与124750相加,得num2
3、将num2与答案的密文520676做比较,如果相同,则密码正确,
将答案密文520676减去124750,得到答案395926
第二题write up
拿到题目,首先反编译,发现java层里有签名检验,判定密码的关键函数是so里的ch函数,
对于签名检验,使用幸运破解器去可以让签名检验失效。
这样子,只要不改变META-INF里的rsa文件,就不会影响签名检验逻辑了。
将so文件拖入ida,寻找符号Java_k2015_a2_Ch_ch,发现ch函数是静态注删的。
attach上去时,发现有反调试,之后定位到反调试有三种:
1、init_array里的最后一个函数是反调试,将dynamic节里的init_array_size减8,
并将init_array节的最后一个offset置0,可以去掉它
2、开一个新线程,不断从/proc/xxx/status里判断是否有进程ptrace自已,并发送信号量来校验线程没有关闭
我修改了getpid函数,让它一直返回1,这样子就检测不到ptrace了
3、代码逻辑中,包括加密后的代码多处从/proc/self/status中判断是否有进程ptrace自己,
对此,我把这些地方用于搞崩溃进程的两行汇编码改成无用的汇编码,密文的部分也一起改了再重加密回写到so文件。
过了反调试后,分析ch函数共有五层
第一层:就是寻找符号Java_k2015_a2_Ch_ch,什么都不干
第二层:反调试,解密并调用第三层,
好像在这层将输入数据写到一个原本是 0x0 0x1 0x2 0x3 0x4 ... 0xf的内存区域mem1
第三层:反调试,解密调用第四层函数,将mem1里的每一个字节分别加上0x0 0x1 0x2 0x3 ... 0xf
第四层:反调试,加密第二层,将第二层的密文的前16字节
0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44, 0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD
与mem1相加,解密调用第五层加密mem1,
并将结果与5C DA 77 2F A3 C6 3E 39 B6 F0 F3 ED 51 5A 99 86比较,如果相同说明密码正确。
第五层:有一个类似aes的算法,我将该算法逆了出来,再推出其解密算法,代码附在最后面,
后来发现,原来是标准的aes算法。
使用以下的代码,将5C DA 77 2F A3 C6 3E 39 B6 F0 F3 ED 51 5A 99 86解密后是
0x8A, 0x1F, 0x4B, 0x6E, 0x59, 0xCA, 0xF2, 0x52, 0x05, 0xCA, 0x27, 0xDE, 0x04, 0xC2, 0xE9, 0xDB
然后,按字节减去
0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44, 0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD
再减去
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
再把抹尾的填充字0x07 0x08 ... 0x0f去掉,得到最终答案
kboloy0
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef unsigned u4;
typedef unsigned short u2;
typedef unsigned char u1;
int K;
const int Nb = 4;
int Nk;
int Nr;
static uint8_t mytable[512] = {
0x63, 0xC6, 0x7C, 0xF8, 0x77, 0xEE, 0x7B, 0xF6, 0xF2, 0xFF, 0x6B, 0xD6, 0x6F, 0xDE, 0xC5, 0x91,
0x30, 0x60, 0x01, 0x02, 0x67, 0xCE, 0x2B, 0x56, 0xFE, 0xE7, 0xD7, 0xB5, 0xAB, 0x4D, 0x76, 0xEC,
0xCA, 0x8F, 0x82, 0x1F, 0xC9, 0x89, 0x7D, 0xFA, 0xFA, 0xEF, 0x59, 0xB2, 0x47, 0x8E, 0xF0, 0xFB,
0xAD, 0x41, 0xD4, 0xB3, 0xA2, 0x5F, 0xAF, 0x45, 0x9C, 0x23, 0xA4, 0x53, 0x72, 0xE4, 0xC0, 0x9B,
0xB7, 0x75, 0xFD, 0xE1, 0x93, 0x3D, 0x26, 0x4C, 0x36, 0x6C, 0x3F, 0x7E, 0xF7, 0xF5, 0xCC, 0x83,
0x34, 0x68, 0xA5, 0x51, 0xE5, 0xD1, 0xF1, 0xF9, 0x71, 0xE2, 0xD8, 0xAB, 0x31, 0x62, 0x15, 0x2A,
0x04, 0x08, 0xC7, 0x95, 0x23, 0x46, 0xC3, 0x9D, 0x18, 0x30, 0x96, 0x37, 0x05, 0x0A, 0x9A, 0x2F,
0x07, 0x0E, 0x12, 0x24, 0x80, 0x1B, 0xE2, 0xDF, 0xEB, 0xCD, 0x27, 0x4E, 0xB2, 0x7F, 0x75, 0xEA,
0x09, 0x12, 0x83, 0x1D, 0x2C, 0x58, 0x1A, 0x34, 0x1B, 0x36, 0x6E, 0xDC, 0x5A, 0xB4, 0xA0, 0x5B,
0x52, 0xA4, 0x3B, 0x76, 0xD6, 0xB7, 0xB3, 0x7D, 0x29, 0x52, 0xE3, 0xDD, 0x2F, 0x5E, 0x84, 0x13,
0x53, 0xA6, 0xD1, 0xB9, 0x00, 0x00, 0xED, 0xC1, 0x20, 0x40, 0xFC, 0xE3, 0xB1, 0x79, 0x5B, 0xB6,
0x6A, 0xD4, 0xCB, 0x8D, 0xBE, 0x67, 0x39, 0x72, 0x4A, 0x94, 0x4C, 0x98, 0x58, 0xB0, 0xCF, 0x85,
0xD0, 0xBB, 0xEF, 0xC5, 0xAA, 0x4F, 0xFB, 0xED, 0x43, 0x86, 0x4D, 0x9A, 0x33, 0x66, 0x85, 0x11,
0x45, 0x8A, 0xF9, 0xE9, 0x02, 0x04, 0x7F, 0xFE, 0x50, 0xA0, 0x3C, 0x78, 0x9F, 0x25, 0xA8, 0x4B,
0x51, 0xA2, 0xA3, 0x5D, 0x40, 0x80, 0x8F, 0x05, 0x92, 0x3F, 0x9D, 0x21, 0x38, 0x70, 0xF5, 0xF1,
0xBC, 0x63, 0xB6, 0x77, 0xDA, 0xAF, 0x21, 0x42, 0x10, 0x20, 0xFF, 0xE5, 0xF3, 0xFD, 0xD2, 0xBF,
0xCD, 0x81, 0x0C, 0x18, 0x13, 0x26, 0xEC, 0xC3, 0x5F, 0xBE, 0x97, 0x35, 0x44, 0x88, 0x17, 0x2E,
0xC4, 0x93, 0xA7, 0x55, 0x7E, 0xFC, 0x3D, 0x7A, 0x64, 0xC8, 0x5D, 0xBA, 0x19, 0x32, 0x73, 0xE6,
0x60, 0xC0, 0x81, 0x19, 0x4F, 0x9E, 0xDC, 0xA3, 0x22, 0x44, 0x2A, 0x54, 0x90, 0x3B, 0x88, 0x0B,
0x46, 0x8C, 0xEE, 0xC7, 0xB8, 0x6B, 0x14, 0x28, 0xDE, 0xA7, 0x5E, 0xBC, 0x0B, 0x16, 0xDB, 0xAD,
0xE0, 0xDB, 0x32, 0x64, 0x3A, 0x74, 0x0A, 0x14, 0x49, 0x92, 0x06, 0x0C, 0x24, 0x48, 0x5C, 0xB8,
0xC2, 0x9F, 0xD3, 0xBD, 0xAC, 0x43, 0x62, 0xC4, 0x91, 0x39, 0x95, 0x31, 0xE4, 0xD3, 0x79, 0xF2,
0xE7, 0xD5, 0xC8, 0x8B, 0x37, 0x6E, 0x6D, 0xDA, 0x8D, 0x01, 0xD5, 0xB1, 0x4E, 0x9C, 0xA9, 0x49,
0x6C, 0xD8, 0x56, 0xAC, 0xF4, 0xF3, 0xEA, 0xCF, 0x65, 0xCA, 0x7A, 0xF4, 0xAE, 0x47, 0x08, 0x10,
0xBA, 0x6F, 0x78, 0xF0, 0x25, 0x4A, 0x2E, 0x5C, 0x1C, 0x38, 0xA6, 0x57, 0xB4, 0x73, 0xC6, 0x97,
0xE8, 0xCB, 0xDD, 0xA1, 0x74, 0xE8, 0x1F, 0x3E, 0x4B, 0x96, 0xBD, 0x61, 0x8B, 0x0D, 0x8A, 0x0F,
0x70, 0xE0, 0x3E, 0x7C, 0xB5, 0x71, 0x66, 0xCC, 0x48, 0x90, 0x03, 0x06, 0xF6, 0xF7, 0x0E, 0x1C,
0x61, 0xC2, 0x35, 0x6A, 0x57, 0xAE, 0xB9, 0x69, 0x86, 0x17, 0xC1, 0x99, 0x1D, 0x3A, 0x9E, 0x27,
0xE1, 0xD9, 0xF8, 0xEB, 0x98, 0x2B, 0x11, 0x22, 0x69, 0xD2, 0xD9, 0xA9, 0x8E, 0x07, 0x94, 0x33,
0x9B, 0x2D, 0x1E, 0x3C, 0x87, 0x15, 0xE9, 0xC9, 0xCE, 0x87, 0x55, 0xAA, 0x28, 0x50, 0xDF, 0xA5,
0x8C, 0x03, 0xA1, 0x59, 0x89, 0x09, 0x0D, 0x1A, 0xBF, 0x65, 0xE6, 0xD7, 0x42, 0x84, 0x68, 0xD0,
0x41, 0x82, 0x99, 0x29, 0x2D, 0x5A, 0x0F, 0x1E, 0xB0, 0x7B, 0x54, 0xA8, 0xBB, 0x6D, 0x16, 0x2C
};
u1 mytable2[] = {
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t myw[] = { 0x7A, 0xC6, 0xCD, 0x6B, 0x9D, 0x7C, 0x2B, 0x6B, 0xB1, 0x59, 0xA4, 0x8D
, 0x80, 0x06, 0x9D, 0xAB, 0x18, 0x0B, 0xA2, 0x34, 0x85, 0x77, 0x89, 0x5F, 0x34, 0x2E, 0x2D, 0xD2
, 0xB4, 0x28, 0xB0, 0x79, 0xAE, 0x86, 0x96, 0xD1, 0x2B, 0xF1, 0x1F, 0x8E, 0x1F, 0xDF, 0x32, 0x5C
, 0xAB, 0xF7, 0x82, 0x25, 0x91, 0xE4, 0xFE, 0xC6, 0xBA, 0x15, 0xE1, 0x48, 0xA5, 0xCA, 0xD3, 0x14
, 0x0E, 0x3D, 0x51, 0x31, 0x56, 0x4F, 0xD9, 0x1F, 0xEC, 0x5A, 0x38, 0x57, 0x49, 0x90, 0xEB, 0x43
, 0x47, 0xAD, 0xBA, 0x72, 0x16, 0xEF, 0x4C, 0xFB, 0xFA, 0xB5, 0x74, 0xAC, 0xB3, 0x25, 0x9F, 0xEF
, 0xF4, 0x88, 0x25, 0x9D, 0x48, 0x50, 0x88, 0xE4, 0xB2, 0xE5, 0xFC, 0x48, 0x01, 0xC0, 0x63, 0xA7
, 0xF5, 0x48, 0x46, 0x3A, 0xC8, 0xB6, 0xDA, 0xFE, 0x7A, 0x53, 0x26, 0xB6, 0x7B, 0x93, 0x45, 0x11
, 0x8E, 0xDB, 0x03, 0x2B, 0x39, 0xAF, 0x63, 0x05, 0x43, 0xFC, 0x45, 0xB3, 0x38, 0x6F, 0x00, 0xA2
, 0xB6, 0xB4, 0x03, 0x89, 0x9E, 0xE1, 0xEE, 0x65, 0xDD, 0x1D, 0xAB, 0xD6, 0xE5, 0x72, 0xAB, 0x74
, 0x53, 0xC6, 0xA8, 0xFD, 0xCA, 0x0C, 0x5A, 0x91, 0x17, 0x11, 0xF1, 0x47, 0xF2, 0x63, 0x5A, 0x33
, 0xA1, 0xA5, 0xF2, 0xCE };
void mykey_expansion(uint8_t *key, uint8_t *w) {
uint8_t tmp[4];
uint8_t i, j;
uint8_t len = Nb*(Nr + 1);
unsigned int v2 = 0x6BCDC67A;
unsigned *pu1 = (unsigned*)w;
unsigned *pu2 = (unsigned*)key;
u2 *pt1 = (u2*)mytable;
u4 *pt2 = (u4*)mytable2;
u4 *pt3 = (u4*)w;
u4 v6 = 0;
for (i = 0; i < 4; ++i) {
pu1[i] = pu2[i];
}
for (i = Nk; i < len; i++) {
if (i%Nk == 0) {
tmp[0] = w[4 * (i - 1) + 0];
tmp[1] = w[4 * (i - 1) + 1];
tmp[2] = w[4 * (i - 1) + 2];
tmp[3] = w[4 * (i - 1) + 3];
u1 pb1 = (u1)pt1[tmp[2]];
u1 pb2 = (u1)pt1[tmp[1]];
u1 pb3 = (u1)pt1[tmp[0]];
u1 pb4 = (u1)pt1[tmp[3]];
u4 pn1 = pb1 << 24 | pb2 << 16 | pb3 << 8 | pb4;
u4 pn2 = pn1 ^ v2;
u4 pni = i - Nk;
int pn3 = (int)pni / (2 ^ 31);
u4 pn4 = (u4)pn3 >> 30;
u4 pn5 = pni + pn4;
u4 pn6 = pt2[pn5 / 4];
v6 = pn6 ^ pn2;
}
else {
v6 ^= v2;
}
pt3[i] = v6;
v2 = pt3[i - Nk + 1];
}
}
u4 byteswap(u1 *p) {
u1 r[4];
r[3] = p[0];
r[2] = p[1];
r[1] = p[2];
r[0] = p[3];
return *(u4*)r;
}
u4 getu1(u4 val, u4 i) {
u1 *va = (u1*)&val;
return va[i];
}
u2 getTableVal(u4 i) {
u2 *myu2Table = (u2*)mytable;
return myu2Table[i];
}
u1 getmix(u2 p) {
u1 v = (p & 0xff) ^ (p >> 8);
return v;
}
u4 finda(u1 a) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i] == a)
return i;
}
}
u4 findb(u1 b) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i + 1] == b)
return i;
}
return 0;
}
u4 findc(u1 c) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i + 1] ^ mytable[2 * i] == c)
return i;
}
return 0;
}
u4 deRounce(u4 nin) {
u1 *pin = (u1*)&nin;
u1 tmp[4] = { 0 };
u1 t[4] = { 0 };
u1 all = pin[0] ^ pin[1] ^ pin[2] ^ pin[3];
tmp[0] = pin[3] ^ all;
tmp[1] = pin[2] ^ all;
tmp[2] = pin[1] ^ all;
tmp[3] = pin[0] ^ all;
u1 i = 0;
u1 j = 0;
for (i = 0; i <= 255; ++i) {
u1 c1 = mytable[2 * i] ^ mytable[2 * i + 1];
u1 b2 = tmp[0] ^ c1;
u1 i2 = findb(b2);
u1 c2 = mytable[2 * i2] ^ mytable[2 * i2 + 1];
u1 b3 = tmp[1] ^ c2;
u1 i3 = findb(b3);
u1 c3 = mytable[2 * i3] ^ mytable[2 * i3 + 1];
u1 b4 = tmp[2] ^ c3;
u1 i4 = findb(b4);
u1 c4 = mytable[2 * i4] ^ mytable[2 * i4 + 1];
u1 b1 = tmp[3] ^ c4;
u1 i1 = findb(b1);
if (i1 == i) {
t[0] = i1;
t[1] = i2;
t[2] = i3;
t[3] = i4;
return *(u4*)t;
}
else
continue;
}
}
void decrypt(u1 *pin, u1 *pout, u1 *w) {
u4 *pt1 = (u4*)w;
u4 ni = 43;
u4 v77 = byteswap(pin + 12) ^ pt1[ni--];
u4 v14 = byteswap(pin + 8) ^ pt1[ni--];
u4 v16 = byteswap(pin + 4) ^ pt1[ni--];
u4 v18 = byteswap(pin) ^ pt1[ni--];
u4 v23 = 0;
u4 v80 = 10;
u2 tmp = 0;
u4 ipt = 4;
u4 v27, v29, v30, v31, v76, v75, v44, v77_2;
u4 uu1 = finda(getu1(v18, 3)) << 24 | finda(getu1(v16, 0)) | finda(getu1(v14, 1)) << 8 | finda(getu1(v77, 2)) << 16;
u4 uu2 = finda(getu1(v16, 3)) << 24 | finda(getu1(v14, 0)) | finda(getu1(v77, 1)) << 8 | finda(getu1(v18, 2)) << 16;
u4 uu3 = finda(getu1(v14, 3)) << 24 | finda(getu1(v77, 0)) | finda(getu1(v18, 1)) << 8 | finda(getu1(v16, 2)) << 16;
u4 uu4 = finda(getu1(v77, 3)) << 24 | finda(getu1(v18, 0)) | finda(getu1(v16, 1)) << 8 | finda(getu1(v14, 2)) << 16;
do {
//uu1 =
v77 = uu4 ^ pt1[ni--];
v14 = uu3 ^ pt1[ni--];
v16 = uu2 ^ pt1[ni--];
v18 = uu1 ^ pt1[ni--];
uu1 = deRounce(v18);
uu2 = deRounce(v16);
uu3 = deRounce(v14);
uu4 = deRounce(v77);
v18 = (uu1 & 0xff) | (uu2 & 0xff000000) | (uu3 & 0xff0000) | (uu4 & 0xff00);
v18 = byteswap((u1*)&v18);
v16 = (uu2 & 0xff) | (uu3 & 0xff000000) | (uu4 & 0xff0000) | (uu1 & 0xff00);
v16 = byteswap((u1*)&v16);
v14 = (uu3 & 0xff) | (uu4 & 0xff000000) | (uu1 & 0xff0000) | (uu2 & 0xff00);
v14 = byteswap((u1*)&v14);
v77 = (uu4 & 0xff) | (uu1 & 0xff000000) | (uu2 & 0xff0000) | (uu3 & 0xff00);
v77 = byteswap((u1*)&v77);
uu1 = v18;
uu2 = v16;
uu3 = v14;
uu4 = v77;
} while (ni >= ipt);
v77 = uu4 ^ pt1[ni--];
v14 = uu3 ^ pt1[ni--];
v16 = uu2 ^ pt1[ni--];
v18 = uu1 ^ pt1[ni--];
u4 tmp2 = 0;
u4 *ptout = (u4*)pout;
ptout[0] = byteswap((u1*)&v18);
ptout[1] = byteswap((u1*)&v16);
ptout[2] = byteswap((u1*)&v14);
ptout[3] = byteswap((u1*)&v77);
}
void encrypt(u1 *pin, u1 *pout, u1 *w) {
u4 *pt1 = (u4*)w;
u4 v77 = byteswap(pin + 12) ^ pt1[3];
u4 v14 = byteswap(pin + 8) ^ pt1[2];
u4 v16 = byteswap(pin + 4) ^ pt1[1];
u4 v18 = byteswap(pin) ^ pt1[0];
u4 v23 = 0;
u4 v80 = 10;
u2 tmp = 0;
u4 ipt = 4;
u4 v27, v29, v30, v31, v76, v75, v44, v77_2;
do {
tmp = getTableVal(getu1(v18, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v16, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v14, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v77, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v76 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v18, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v76);
u4 myv = deRounce(v76 ^ pt1[ipt - 1]);
tmp = getTableVal(getu1(v16, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v14, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v77, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v18, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v75 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v16, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v75);
tmp = getTableVal(getu1(v14, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v77, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v18, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v16, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v44 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v14, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v44);
tmp = getTableVal(getu1(v77, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v18, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v16, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v14, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v77_2 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v77, v27 ^ v29 ^ v30 ^ v31, pt1[ipt-1], v77_2);
v77 = v77_2;
v14 = v44;
v16 = v75;
v18 = v76;
v23++;
} while (v23 + 1 < v80); //*/
u4 tmp2 = 0;
u4 *ptout = (u4*)pout;
tmp2 = (getTableVal(getu1(v18, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v16, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v14, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v77, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[0] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v16, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v14, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v77, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v18, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[1] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v14, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v77, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v18, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v16, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[2] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v77, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v18, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v16, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v14, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[3] = byteswap((u1*)&tmp2);
return;
}
u1 cr[256] = { 0 };
void printc(){
int i = 0;
for (i = 0; i < 256; ++i) {
u1 t = mytable[2 * i] ^ mytable[2 * i + 1];
if (cr[t]) {
printf("haha");
}
else {
cr[t] = 1;
}
printf("%02x ", t);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
}
int main(int argc, char *argv[]) {
uint8_t i;
u1 sub_key[] = { 0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44,
0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD }; //第四层的相加密钥
uint8_t key[] = {
0x7A, 0xC6, 0xCD, 0x6B, 0x9D, 0x7C, 0x2B, 0x6B, 0xB1, 0x59, 0xA4, 0x8D, 0x80, 0x06, 0x9D, 0xAB
}; //第五层的密钥
/*
uint8_t in[] = { //第五层加密前的明文
0x8A, 0x1F, 0x4B, 0x6E, 0x59, 0xCA, 0xF2, 0x52, 0x05, 0xCA, 0x27, 0xDE, 0x04, 0xC2, 0xE9, 0xDB };
//*/
/*
uint8_t in[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t out[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//*/
uint8_t out[] = {
0x5C, 0xDA, 0x77, 0x2F, 0xA3, 0xC6, 0x3E, 0x39, 0xB6, 0xF0, 0xF3, 0xED, 0x51, 0x5A, 0x99, 0x86 };
//*/
//uint8_t out[16]; // 第五层加密后的密文
uint8_t in[16];
uint8_t *w; // expanded key
Nk = 4; Nr = 10;
//printc();
w = (uint8_t*)malloc(Nb*(Nr + 1) * 4);
//w = myw;
mykey_expansion(key, w); //可以省去,改成直接从内存dump出的myw数组
//memset(w, 0, 44);
//encrypt(in /* in */, out /* out */, w /* expanded key */);
decrypt(out, in, w); //从第五层密文还原第五层明文
for (i = 0; i < 16; ++i) {
in[i] -= (sub_key[i] + (u1)i); //第四层与第三层解密
if (in[i] == (u1)i) //去掉未尾的填充数据
in[i] = 0;
}
printf("answer is %s\n", in);
getchar();
}
拿到题目,首先是反编译和dex2jar
在jad-gui里看不到关键类check的java源码,
然后在smali代码基础上,去掉所有的synthetic字段,并把所以有的.catch替换为#.catch,
再重新生成dex文件,就可以在jad-gui里看到check类的java源码。
在jad-gui中看代码时,发现,它还做了混淆,有大量的数组赋值语句及反射调用,无法阅读,
但可以看到代码结构基本上是线性的,所以,只要盯着保存有用户输入的密码的那几个寄存器及if语句下断点,就能跟踪到关键逻辑。
关键逻辑有三个:
1、将用户输入数据转化为数字num1,所以密码一定是数字
2、将num1与1 5 9 ... 1001相加,但在下一步比较中发现是与124750相加,得num2
3、将num2与答案的密文520676做比较,如果相同,则密码正确,
将答案密文520676减去124750,得到答案395926
第二题write up
拿到题目,首先反编译,发现java层里有签名检验,判定密码的关键函数是so里的ch函数,
对于签名检验,使用幸运破解器去可以让签名检验失效。
这样子,只要不改变META-INF里的rsa文件,就不会影响签名检验逻辑了。
将so文件拖入ida,寻找符号Java_k2015_a2_Ch_ch,发现ch函数是静态注删的。
attach上去时,发现有反调试,之后定位到反调试有三种:
1、init_array里的最后一个函数是反调试,将dynamic节里的init_array_size减8,
并将init_array节的最后一个offset置0,可以去掉它
2、开一个新线程,不断从/proc/xxx/status里判断是否有进程ptrace自已,并发送信号量来校验线程没有关闭
我修改了getpid函数,让它一直返回1,这样子就检测不到ptrace了
3、代码逻辑中,包括加密后的代码多处从/proc/self/status中判断是否有进程ptrace自己,
对此,我把这些地方用于搞崩溃进程的两行汇编码改成无用的汇编码,密文的部分也一起改了再重加密回写到so文件。
过了反调试后,分析ch函数共有五层
第一层:就是寻找符号Java_k2015_a2_Ch_ch,什么都不干
第二层:反调试,解密并调用第三层,
好像在这层将输入数据写到一个原本是 0x0 0x1 0x2 0x3 0x4 ... 0xf的内存区域mem1
第三层:反调试,解密调用第四层函数,将mem1里的每一个字节分别加上0x0 0x1 0x2 0x3 ... 0xf
第四层:反调试,加密第二层,将第二层的密文的前16字节
0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44, 0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD
与mem1相加,解密调用第五层加密mem1,
并将结果与5C DA 77 2F A3 C6 3E 39 B6 F0 F3 ED 51 5A 99 86比较,如果相同说明密码正确。
第五层:有一个类似aes的算法,我将该算法逆了出来,再推出其解密算法,代码附在最后面,
后来发现,原来是标准的aes算法。
使用以下的代码,将5C DA 77 2F A3 C6 3E 39 B6 F0 F3 ED 51 5A 99 86解密后是
0x8A, 0x1F, 0x4B, 0x6E, 0x59, 0xCA, 0xF2, 0x52, 0x05, 0xCA, 0x27, 0xDE, 0x04, 0xC2, 0xE9, 0xDB
然后,按字节减去
0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44, 0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD
再减去
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
再把抹尾的填充字0x07 0x08 ... 0x0f去掉,得到最终答案
kboloy0
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef unsigned u4;
typedef unsigned short u2;
typedef unsigned char u1;
int K;
const int Nb = 4;
int Nk;
int Nr;
static uint8_t mytable[512] = {
0x63, 0xC6, 0x7C, 0xF8, 0x77, 0xEE, 0x7B, 0xF6, 0xF2, 0xFF, 0x6B, 0xD6, 0x6F, 0xDE, 0xC5, 0x91,
0x30, 0x60, 0x01, 0x02, 0x67, 0xCE, 0x2B, 0x56, 0xFE, 0xE7, 0xD7, 0xB5, 0xAB, 0x4D, 0x76, 0xEC,
0xCA, 0x8F, 0x82, 0x1F, 0xC9, 0x89, 0x7D, 0xFA, 0xFA, 0xEF, 0x59, 0xB2, 0x47, 0x8E, 0xF0, 0xFB,
0xAD, 0x41, 0xD4, 0xB3, 0xA2, 0x5F, 0xAF, 0x45, 0x9C, 0x23, 0xA4, 0x53, 0x72, 0xE4, 0xC0, 0x9B,
0xB7, 0x75, 0xFD, 0xE1, 0x93, 0x3D, 0x26, 0x4C, 0x36, 0x6C, 0x3F, 0x7E, 0xF7, 0xF5, 0xCC, 0x83,
0x34, 0x68, 0xA5, 0x51, 0xE5, 0xD1, 0xF1, 0xF9, 0x71, 0xE2, 0xD8, 0xAB, 0x31, 0x62, 0x15, 0x2A,
0x04, 0x08, 0xC7, 0x95, 0x23, 0x46, 0xC3, 0x9D, 0x18, 0x30, 0x96, 0x37, 0x05, 0x0A, 0x9A, 0x2F,
0x07, 0x0E, 0x12, 0x24, 0x80, 0x1B, 0xE2, 0xDF, 0xEB, 0xCD, 0x27, 0x4E, 0xB2, 0x7F, 0x75, 0xEA,
0x09, 0x12, 0x83, 0x1D, 0x2C, 0x58, 0x1A, 0x34, 0x1B, 0x36, 0x6E, 0xDC, 0x5A, 0xB4, 0xA0, 0x5B,
0x52, 0xA4, 0x3B, 0x76, 0xD6, 0xB7, 0xB3, 0x7D, 0x29, 0x52, 0xE3, 0xDD, 0x2F, 0x5E, 0x84, 0x13,
0x53, 0xA6, 0xD1, 0xB9, 0x00, 0x00, 0xED, 0xC1, 0x20, 0x40, 0xFC, 0xE3, 0xB1, 0x79, 0x5B, 0xB6,
0x6A, 0xD4, 0xCB, 0x8D, 0xBE, 0x67, 0x39, 0x72, 0x4A, 0x94, 0x4C, 0x98, 0x58, 0xB0, 0xCF, 0x85,
0xD0, 0xBB, 0xEF, 0xC5, 0xAA, 0x4F, 0xFB, 0xED, 0x43, 0x86, 0x4D, 0x9A, 0x33, 0x66, 0x85, 0x11,
0x45, 0x8A, 0xF9, 0xE9, 0x02, 0x04, 0x7F, 0xFE, 0x50, 0xA0, 0x3C, 0x78, 0x9F, 0x25, 0xA8, 0x4B,
0x51, 0xA2, 0xA3, 0x5D, 0x40, 0x80, 0x8F, 0x05, 0x92, 0x3F, 0x9D, 0x21, 0x38, 0x70, 0xF5, 0xF1,
0xBC, 0x63, 0xB6, 0x77, 0xDA, 0xAF, 0x21, 0x42, 0x10, 0x20, 0xFF, 0xE5, 0xF3, 0xFD, 0xD2, 0xBF,
0xCD, 0x81, 0x0C, 0x18, 0x13, 0x26, 0xEC, 0xC3, 0x5F, 0xBE, 0x97, 0x35, 0x44, 0x88, 0x17, 0x2E,
0xC4, 0x93, 0xA7, 0x55, 0x7E, 0xFC, 0x3D, 0x7A, 0x64, 0xC8, 0x5D, 0xBA, 0x19, 0x32, 0x73, 0xE6,
0x60, 0xC0, 0x81, 0x19, 0x4F, 0x9E, 0xDC, 0xA3, 0x22, 0x44, 0x2A, 0x54, 0x90, 0x3B, 0x88, 0x0B,
0x46, 0x8C, 0xEE, 0xC7, 0xB8, 0x6B, 0x14, 0x28, 0xDE, 0xA7, 0x5E, 0xBC, 0x0B, 0x16, 0xDB, 0xAD,
0xE0, 0xDB, 0x32, 0x64, 0x3A, 0x74, 0x0A, 0x14, 0x49, 0x92, 0x06, 0x0C, 0x24, 0x48, 0x5C, 0xB8,
0xC2, 0x9F, 0xD3, 0xBD, 0xAC, 0x43, 0x62, 0xC4, 0x91, 0x39, 0x95, 0x31, 0xE4, 0xD3, 0x79, 0xF2,
0xE7, 0xD5, 0xC8, 0x8B, 0x37, 0x6E, 0x6D, 0xDA, 0x8D, 0x01, 0xD5, 0xB1, 0x4E, 0x9C, 0xA9, 0x49,
0x6C, 0xD8, 0x56, 0xAC, 0xF4, 0xF3, 0xEA, 0xCF, 0x65, 0xCA, 0x7A, 0xF4, 0xAE, 0x47, 0x08, 0x10,
0xBA, 0x6F, 0x78, 0xF0, 0x25, 0x4A, 0x2E, 0x5C, 0x1C, 0x38, 0xA6, 0x57, 0xB4, 0x73, 0xC6, 0x97,
0xE8, 0xCB, 0xDD, 0xA1, 0x74, 0xE8, 0x1F, 0x3E, 0x4B, 0x96, 0xBD, 0x61, 0x8B, 0x0D, 0x8A, 0x0F,
0x70, 0xE0, 0x3E, 0x7C, 0xB5, 0x71, 0x66, 0xCC, 0x48, 0x90, 0x03, 0x06, 0xF6, 0xF7, 0x0E, 0x1C,
0x61, 0xC2, 0x35, 0x6A, 0x57, 0xAE, 0xB9, 0x69, 0x86, 0x17, 0xC1, 0x99, 0x1D, 0x3A, 0x9E, 0x27,
0xE1, 0xD9, 0xF8, 0xEB, 0x98, 0x2B, 0x11, 0x22, 0x69, 0xD2, 0xD9, 0xA9, 0x8E, 0x07, 0x94, 0x33,
0x9B, 0x2D, 0x1E, 0x3C, 0x87, 0x15, 0xE9, 0xC9, 0xCE, 0x87, 0x55, 0xAA, 0x28, 0x50, 0xDF, 0xA5,
0x8C, 0x03, 0xA1, 0x59, 0x89, 0x09, 0x0D, 0x1A, 0xBF, 0x65, 0xE6, 0xD7, 0x42, 0x84, 0x68, 0xD0,
0x41, 0x82, 0x99, 0x29, 0x2D, 0x5A, 0x0F, 0x1E, 0xB0, 0x7B, 0x54, 0xA8, 0xBB, 0x6D, 0x16, 0x2C
};
u1 mytable2[] = {
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t myw[] = { 0x7A, 0xC6, 0xCD, 0x6B, 0x9D, 0x7C, 0x2B, 0x6B, 0xB1, 0x59, 0xA4, 0x8D
, 0x80, 0x06, 0x9D, 0xAB, 0x18, 0x0B, 0xA2, 0x34, 0x85, 0x77, 0x89, 0x5F, 0x34, 0x2E, 0x2D, 0xD2
, 0xB4, 0x28, 0xB0, 0x79, 0xAE, 0x86, 0x96, 0xD1, 0x2B, 0xF1, 0x1F, 0x8E, 0x1F, 0xDF, 0x32, 0x5C
, 0xAB, 0xF7, 0x82, 0x25, 0x91, 0xE4, 0xFE, 0xC6, 0xBA, 0x15, 0xE1, 0x48, 0xA5, 0xCA, 0xD3, 0x14
, 0x0E, 0x3D, 0x51, 0x31, 0x56, 0x4F, 0xD9, 0x1F, 0xEC, 0x5A, 0x38, 0x57, 0x49, 0x90, 0xEB, 0x43
, 0x47, 0xAD, 0xBA, 0x72, 0x16, 0xEF, 0x4C, 0xFB, 0xFA, 0xB5, 0x74, 0xAC, 0xB3, 0x25, 0x9F, 0xEF
, 0xF4, 0x88, 0x25, 0x9D, 0x48, 0x50, 0x88, 0xE4, 0xB2, 0xE5, 0xFC, 0x48, 0x01, 0xC0, 0x63, 0xA7
, 0xF5, 0x48, 0x46, 0x3A, 0xC8, 0xB6, 0xDA, 0xFE, 0x7A, 0x53, 0x26, 0xB6, 0x7B, 0x93, 0x45, 0x11
, 0x8E, 0xDB, 0x03, 0x2B, 0x39, 0xAF, 0x63, 0x05, 0x43, 0xFC, 0x45, 0xB3, 0x38, 0x6F, 0x00, 0xA2
, 0xB6, 0xB4, 0x03, 0x89, 0x9E, 0xE1, 0xEE, 0x65, 0xDD, 0x1D, 0xAB, 0xD6, 0xE5, 0x72, 0xAB, 0x74
, 0x53, 0xC6, 0xA8, 0xFD, 0xCA, 0x0C, 0x5A, 0x91, 0x17, 0x11, 0xF1, 0x47, 0xF2, 0x63, 0x5A, 0x33
, 0xA1, 0xA5, 0xF2, 0xCE };
void mykey_expansion(uint8_t *key, uint8_t *w) {
uint8_t tmp[4];
uint8_t i, j;
uint8_t len = Nb*(Nr + 1);
unsigned int v2 = 0x6BCDC67A;
unsigned *pu1 = (unsigned*)w;
unsigned *pu2 = (unsigned*)key;
u2 *pt1 = (u2*)mytable;
u4 *pt2 = (u4*)mytable2;
u4 *pt3 = (u4*)w;
u4 v6 = 0;
for (i = 0; i < 4; ++i) {
pu1[i] = pu2[i];
}
for (i = Nk; i < len; i++) {
if (i%Nk == 0) {
tmp[0] = w[4 * (i - 1) + 0];
tmp[1] = w[4 * (i - 1) + 1];
tmp[2] = w[4 * (i - 1) + 2];
tmp[3] = w[4 * (i - 1) + 3];
u1 pb1 = (u1)pt1[tmp[2]];
u1 pb2 = (u1)pt1[tmp[1]];
u1 pb3 = (u1)pt1[tmp[0]];
u1 pb4 = (u1)pt1[tmp[3]];
u4 pn1 = pb1 << 24 | pb2 << 16 | pb3 << 8 | pb4;
u4 pn2 = pn1 ^ v2;
u4 pni = i - Nk;
int pn3 = (int)pni / (2 ^ 31);
u4 pn4 = (u4)pn3 >> 30;
u4 pn5 = pni + pn4;
u4 pn6 = pt2[pn5 / 4];
v6 = pn6 ^ pn2;
}
else {
v6 ^= v2;
}
pt3[i] = v6;
v2 = pt3[i - Nk + 1];
}
}
u4 byteswap(u1 *p) {
u1 r[4];
r[3] = p[0];
r[2] = p[1];
r[1] = p[2];
r[0] = p[3];
return *(u4*)r;
}
u4 getu1(u4 val, u4 i) {
u1 *va = (u1*)&val;
return va[i];
}
u2 getTableVal(u4 i) {
u2 *myu2Table = (u2*)mytable;
return myu2Table[i];
}
u1 getmix(u2 p) {
u1 v = (p & 0xff) ^ (p >> 8);
return v;
}
u4 finda(u1 a) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i] == a)
return i;
}
}
u4 findb(u1 b) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i + 1] == b)
return i;
}
return 0;
}
u4 findc(u1 c) {
u4 i = 0;
for (i = 0; i <= 255; ++i) {
if (mytable[2 * i + 1] ^ mytable[2 * i] == c)
return i;
}
return 0;
}
u4 deRounce(u4 nin) {
u1 *pin = (u1*)&nin;
u1 tmp[4] = { 0 };
u1 t[4] = { 0 };
u1 all = pin[0] ^ pin[1] ^ pin[2] ^ pin[3];
tmp[0] = pin[3] ^ all;
tmp[1] = pin[2] ^ all;
tmp[2] = pin[1] ^ all;
tmp[3] = pin[0] ^ all;
u1 i = 0;
u1 j = 0;
for (i = 0; i <= 255; ++i) {
u1 c1 = mytable[2 * i] ^ mytable[2 * i + 1];
u1 b2 = tmp[0] ^ c1;
u1 i2 = findb(b2);
u1 c2 = mytable[2 * i2] ^ mytable[2 * i2 + 1];
u1 b3 = tmp[1] ^ c2;
u1 i3 = findb(b3);
u1 c3 = mytable[2 * i3] ^ mytable[2 * i3 + 1];
u1 b4 = tmp[2] ^ c3;
u1 i4 = findb(b4);
u1 c4 = mytable[2 * i4] ^ mytable[2 * i4 + 1];
u1 b1 = tmp[3] ^ c4;
u1 i1 = findb(b1);
if (i1 == i) {
t[0] = i1;
t[1] = i2;
t[2] = i3;
t[3] = i4;
return *(u4*)t;
}
else
continue;
}
}
void decrypt(u1 *pin, u1 *pout, u1 *w) {
u4 *pt1 = (u4*)w;
u4 ni = 43;
u4 v77 = byteswap(pin + 12) ^ pt1[ni--];
u4 v14 = byteswap(pin + 8) ^ pt1[ni--];
u4 v16 = byteswap(pin + 4) ^ pt1[ni--];
u4 v18 = byteswap(pin) ^ pt1[ni--];
u4 v23 = 0;
u4 v80 = 10;
u2 tmp = 0;
u4 ipt = 4;
u4 v27, v29, v30, v31, v76, v75, v44, v77_2;
u4 uu1 = finda(getu1(v18, 3)) << 24 | finda(getu1(v16, 0)) | finda(getu1(v14, 1)) << 8 | finda(getu1(v77, 2)) << 16;
u4 uu2 = finda(getu1(v16, 3)) << 24 | finda(getu1(v14, 0)) | finda(getu1(v77, 1)) << 8 | finda(getu1(v18, 2)) << 16;
u4 uu3 = finda(getu1(v14, 3)) << 24 | finda(getu1(v77, 0)) | finda(getu1(v18, 1)) << 8 | finda(getu1(v16, 2)) << 16;
u4 uu4 = finda(getu1(v77, 3)) << 24 | finda(getu1(v18, 0)) | finda(getu1(v16, 1)) << 8 | finda(getu1(v14, 2)) << 16;
do {
//uu1 =
v77 = uu4 ^ pt1[ni--];
v14 = uu3 ^ pt1[ni--];
v16 = uu2 ^ pt1[ni--];
v18 = uu1 ^ pt1[ni--];
uu1 = deRounce(v18);
uu2 = deRounce(v16);
uu3 = deRounce(v14);
uu4 = deRounce(v77);
v18 = (uu1 & 0xff) | (uu2 & 0xff000000) | (uu3 & 0xff0000) | (uu4 & 0xff00);
v18 = byteswap((u1*)&v18);
v16 = (uu2 & 0xff) | (uu3 & 0xff000000) | (uu4 & 0xff0000) | (uu1 & 0xff00);
v16 = byteswap((u1*)&v16);
v14 = (uu3 & 0xff) | (uu4 & 0xff000000) | (uu1 & 0xff0000) | (uu2 & 0xff00);
v14 = byteswap((u1*)&v14);
v77 = (uu4 & 0xff) | (uu1 & 0xff000000) | (uu2 & 0xff0000) | (uu3 & 0xff00);
v77 = byteswap((u1*)&v77);
uu1 = v18;
uu2 = v16;
uu3 = v14;
uu4 = v77;
} while (ni >= ipt);
v77 = uu4 ^ pt1[ni--];
v14 = uu3 ^ pt1[ni--];
v16 = uu2 ^ pt1[ni--];
v18 = uu1 ^ pt1[ni--];
u4 tmp2 = 0;
u4 *ptout = (u4*)pout;
ptout[0] = byteswap((u1*)&v18);
ptout[1] = byteswap((u1*)&v16);
ptout[2] = byteswap((u1*)&v14);
ptout[3] = byteswap((u1*)&v77);
}
void encrypt(u1 *pin, u1 *pout, u1 *w) {
u4 *pt1 = (u4*)w;
u4 v77 = byteswap(pin + 12) ^ pt1[3];
u4 v14 = byteswap(pin + 8) ^ pt1[2];
u4 v16 = byteswap(pin + 4) ^ pt1[1];
u4 v18 = byteswap(pin) ^ pt1[0];
u4 v23 = 0;
u4 v80 = 10;
u2 tmp = 0;
u4 ipt = 4;
u4 v27, v29, v30, v31, v76, v75, v44, v77_2;
do {
tmp = getTableVal(getu1(v18, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v16, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v14, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v77, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v76 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v18, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v76);
u4 myv = deRounce(v76 ^ pt1[ipt - 1]);
tmp = getTableVal(getu1(v16, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v14, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v77, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v18, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v75 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v16, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v75);
tmp = getTableVal(getu1(v14, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v77, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v18, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v16, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v44 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v14, v27 ^ v29 ^ v30 ^ v31, pt1[ipt - 1], v44);
tmp = getTableVal(getu1(v77, 3));
v27 = ((tmp & 0xff) << 8) | (tmp << 16) | getmix(tmp);
tmp = getTableVal(getu1(v18, 2));
v29 = (tmp & 0xff) | (tmp << 8) | (getmix(tmp) << 24);
tmp = getTableVal(getu1(v16, 1));
v30 = (tmp) | (tmp << 24) | (getmix(tmp) << 16);
tmp = getTableVal(getu1(v14, 0));
v31 = ((tmp & 0xff) << 16) | (tmp << 24) | (getmix(tmp) << 8) | (tmp >> 8);
v77_2 = pt1[ipt++] ^ v27 ^ v29 ^ v30 ^ v31;
//printf("show %p %p %p %p\n", v77, v27 ^ v29 ^ v30 ^ v31, pt1[ipt-1], v77_2);
v77 = v77_2;
v14 = v44;
v16 = v75;
v18 = v76;
v23++;
} while (v23 + 1 < v80); //*/
u4 tmp2 = 0;
u4 *ptout = (u4*)pout;
tmp2 = (getTableVal(getu1(v18, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v16, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v14, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v77, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[0] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v16, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v14, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v77, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v18, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[1] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v14, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v77, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v18, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v16, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[2] = byteswap((u1*)&tmp2);
tmp2 = (getTableVal(getu1(v77, 3)) & 0xff) << 24;
tmp2 |= (getTableVal(getu1(v18, 2)) & 0xff) << 16;
tmp2 |= (getTableVal(getu1(v16, 1)) & 0xff) << 8;
tmp2 |= (getTableVal(getu1(v14, 0)) & 0xff);
tmp2 ^= pt1[ipt++];
ptout[3] = byteswap((u1*)&tmp2);
return;
}
u1 cr[256] = { 0 };
void printc(){
int i = 0;
for (i = 0; i < 256; ++i) {
u1 t = mytable[2 * i] ^ mytable[2 * i + 1];
if (cr[t]) {
printf("haha");
}
else {
cr[t] = 1;
}
printf("%02x ", t);
if ((i + 1) % 16 == 0) {
printf("\n");
}
}
}
int main(int argc, char *argv[]) {
uint8_t i;
u1 sub_key[] = { 0x1F, 0xBC, 0xDA, 0xFF, 0xE6, 0x4C, 0xBC, 0x44,
0xF5, 0xB8, 0x13, 0xC8, 0xEC, 0xA8, 0xCD, 0xBD }; //第四层的相加密钥
uint8_t key[] = {
0x7A, 0xC6, 0xCD, 0x6B, 0x9D, 0x7C, 0x2B, 0x6B, 0xB1, 0x59, 0xA4, 0x8D, 0x80, 0x06, 0x9D, 0xAB
}; //第五层的密钥
/*
uint8_t in[] = { //第五层加密前的明文
0x8A, 0x1F, 0x4B, 0x6E, 0x59, 0xCA, 0xF2, 0x52, 0x05, 0xCA, 0x27, 0xDE, 0x04, 0xC2, 0xE9, 0xDB };
//*/
/*
uint8_t in[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t out[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//*/
uint8_t out[] = {
0x5C, 0xDA, 0x77, 0x2F, 0xA3, 0xC6, 0x3E, 0x39, 0xB6, 0xF0, 0xF3, 0xED, 0x51, 0x5A, 0x99, 0x86 };
//*/
//uint8_t out[16]; // 第五层加密后的密文
uint8_t in[16];
uint8_t *w; // expanded key
Nk = 4; Nr = 10;
//printc();
w = (uint8_t*)malloc(Nb*(Nr + 1) * 4);
//w = myw;
mykey_expansion(key, w); //可以省去,改成直接从内存dump出的myw数组
//memset(w, 0, 44);
//encrypt(in /* in */, out /* out */, w /* expanded key */);
decrypt(out, in, w); //从第五层密文还原第五层明文
for (i = 0; i < 16; ++i) {
in[i] -= (sub_key[i] + (u1)i); //第四层与第三层解密
if (in[i] == (u1)i) //去掉未尾的填充数据
in[i] = 0;
}
printf("answer is %s\n", in);
getchar();
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
- deodex android o的vdex文件 21439
- [原创][转帖]分享一个最好用的root方法,大家一起来捣鼓一下 5393
- 逆向修改手机内核,绕过反调试 57062
- 没有标题的水贴 5632
看原图
赞赏
雪币:
留言: