记一次手动脱壳
文件可以查到是一个壳,不过并不是常见的UPX壳,可以发现是一个压缩壳,所以我们可以尝试使用ESP定律脱壳。

切换到调试器,可以发现在程序入口处又PUSHAD和PUSHFD保存目前的寄存器,脱壳完成后就会还原寄存器,我们就往栈那边下一个访问断点

继续执行行,停在了

再前进一步

猜测这个就是OEP,我们直接dump出来(一定要重建导入表),然后拖入IDA
根据字符串定位到函数:

明显有混淆,处理一下

逻辑很清晰,核心就是一个tea的加密,这个我们查看这个tea加密函数,可以发现是被混淆了的

混淆出现在call $+5上,这个混淆很有意思,call $+5意思是目前字节的后5个字节作为起始位置,call一次,call操作会压入返回地址(就是add语句的地址),返回地址就在栈顶,call指令的长度恰好就是5,于是直接就到了add语句,add语句实现的就是把栈顶元素的值+7,var_44的值是-44,操作之后call的返回地址就变成了
00EC10E7 由于混淆,这里变成了奇奇怪怪的指令
在动调中可以观察的更加明显

我们将其复原

这是个复杂的加密,根据已知信息复原一下

遇到这种复杂加密,我们就看数据在哪里被修改了就行,干扰操作不需要关注
分析一下,就能发现一个很像tea加密的结构:

相关的数据操作也只在这里发生了,基本可以断定这里就是加密的地方,其他的不用关注。
除了加密,我们还需要知道循环了多少次,for循环里面的条件非常复杂,我们可以看n0x26 ,里面有大于等于38就跳出的判断,可以猜测就是38次,不放心可以动调测试。
具体逆向过程可以直接丢给AI解
现在可以写出逆向代码
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
| void __cdecl init_tea_pwd(int tea_pwd) { int i;
for (i = 0; i < 4; ++i) *(_DWORD*)(tea_pwd + 4 * i) = rand(); } #define C 0x114514u #define ROUNDS 0x26u
static inline uint32_t rol32(uint32_t x, unsigned int r) { r &= 31; return (x << r) | (x >> (32 - r)); }
static inline uint32_t ror32(uint32_t x, unsigned int r) { r &= 31; return (x >> r) | (x << (32 - r)); }
unsigned int* __cdecl tea_decrypt(unsigned int* a2, unsigned int* a3, const unsigned int* key) { uint32_t v0 = *a2; uint32_t v1 = *a3;
uint32_t v11 = ROUNDS * C;
for (int r = ROUNDS - 1; r >= 0; --r) { uint32_t s2 = v11; uint32_t rot2 = s2 % 5u + 1u; uint32_t k1 = key[(s2 >> 11) & 3u];
uint32_t t2 = v0 + (((v0 >> 5) ^ (16u * v0))); uint32_t mix2 = (k1 + s2) ^ t2;
v1 = ror32(v1, rot2) - mix2;
uint32_t s = s2 - C; uint32_t rot1 = s % 7u + 1u; uint32_t k0 = key[s & 3u];
uint32_t t1 = v1 + (((v1 >> 5) ^ (16u * v1))); uint32_t mix1 = (k0 + s) ^ t1;
v0 = ror32(v0, rot1) - mix1;
v11 = s; }
*a2 = v0; *a3 = v1; return a3; } int main() { srand(2025); unsigned int enflag[10] = { 0xD7E2CB3E, 0x1FDAAA30, 0x795CC461, 0x935C4CE6, 0xF587B2C4, 0x71417D92, 0x30059C32, 0x8F07B51F, 0xB53BB9AA, 0x9B981529 }; _DWORD* tea_pwd =(_DWORD*) malloc(16); init_tea_pwd((uint32)tea_pwd);
for(int i=8;i>=0;--i) tea_decrypt(&enflag[i], &enflag[i+1], (uint32*)tea_pwd); char buff[40] = {0};
for (int i = 0; i != 10; ++i) { buff[i * 4] = BYTE3(enflag[i]); buff[i * 4 + 1] = BYTE2(enflag[i]); buff[i * 4 + 2] = BYTE1(enflag[i]); buff[i * 4 + 3] = BYTE0(enflag[i]); } printf("%s", buff); printf("\n"); free(tea_pwd); return 0;
}
|
ISCTF{XTEA_14_POFP_N0_0ne_Can_Beat!!!!!}