fisher
0x01 解密
ida打开文件,main函数:

将输入加密为str1与密文比较,加密逻辑为换表base64;

fake flag;
尝试动调也错,感觉strcmp不能正常执行;
动调进入strcmp,发现系统指令被修改为一个jmp,进入后出现真正的加密函数

输入每八位执行一个tea加密(sub_7ff),v5是密文,v9是key(后八位是0);
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #include<iostream> #include<string> #include<algorithm> #include<vector> #include<print> #include<stdint.h> using namespace std;
unsigned char v5[64]={}; unsigned char v9[16]={};
void tea_dec(uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1]; // v0、v1分别是密文的左、右半部分 uint32_t delta = -1835914967; //作为sum每次累加的变化值,题目中往往会修改此值 uint32_t sum = 32 * delta; //此处需要分析32轮加密结束后sum的值与delta的变化, 以此处加密为例子,32轮每次sum+=delta,因此最后sum=32*delta for (int i = 0; i < 32; i++) { // tea加密进行32轮 //根据加密时的顺序颠倒下面3行的顺序,将加法改为减法(异或部分都是整体,不用管),就是逆向解密过程 v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]); sum -= delta; } // 因此解密后的内容要还给v数组 v[0] = v0; v[1] = v1; } int main() { v5[0] = 8; v5[1] = -18; v5[2] = 89; v5[3] = 77; v5[4] = 13; v5[5] = -32; v5[6] = -64; v5[7] = -119; v5[8] = -95; v5[9] = -104; v5[10] = -78; v5[11] = -69; v5[12] = -49; v5[13] = 112; v5[14] = 127; v5[15] = -27; v5[16] = -24; v5[17] = 47; v5[18] = -102; v5[19] = -118; v5[20] = 32; v5[21] = -53; v5[22] = 116; v5[23] = 18; v5[24] = -14; v5[25] = 48; v5[26] = 120; v5[27] = 31; v5[28] = 14; v5[29] = -21; v5[30] = 31; v5[31] = -120; v5[32] = -56; v5[33] = -68; v5[34] = 78; v5[35] = -8; v5[36] = 82; v5[37] = 19; v5[38] = 83; v5[39] = -117; v5[40] = -99; v5[41] = -65; v5[42] = 102; v5[43] = 11; v5[44] = 106; v5[45] = -84; v5[46] = 33; v5[47] = 79; v5[48] = -23; v5[49] = 31; v5[50] = 70; v5[51] = 70; v5[52] = -98; v5[53] = -53; v5[54] = -6; v5[55] = 99; v5[56] = -93; v5[57] = -123; v5[58] = 20; v5[59] = -55; v5[60] = 46; v5[61] = -9; v5[62] = 16; v5[63] = -59; v9[0] = 17; v9[1] = 34; v9[2] = 51; v9[3] = 68; v9[4] = 85; v9[5] = 102; v9[6] = 119; v9[7] = -120; for (int i = 0;i <= 7;i++) { tea_dec((uint32_t*)(v5+8*i), (uint32_t*)v9); } for (char a : v5) cout<<a; }
|
输出:zCN7zTJg0xnEzxjJywV50xn53CvO4vZPyxrF2SzFzwr53SBQ0fZV1TvOxSj70xrZ;
因为调用的是str1,所以还要base64回去,
flag{Fisherman_is_very_satisfied_with_your_bait}
0x02 hook原理分析
查看真实加密函数调用,找到这样的函数

查询后是一个inline_hook
将strcmp的函数地址存到strcmp_0中,然后执行下面函数(sub_1150或a2即为加密函数)

9727转hex为0x25ff,转小端ff 25为jmp的字节码,小端存进qword src[0]的低四位,
两行结束src[0]为00 00 00 00 ff 25 00 00 ,
第三行从第七位00开始换为a2的地址,构建出src为jmp a2的指令,
再将新的src地址赋给*lpadress,即strcmp_0的地址,即原来库函数strcmp的地址,
这样就完成了对strcmp的hook动态替换。