-
-
[原创]CTF2017 第十一题 ToBeBetterCrackMe
-
发表于: 2017-6-22 21:50 3303
-
本章主要说一些重点逻辑,记录坑点,囧,我居然在 伪模式 解无解数学题花了不少时间。
查找引用则找到重要函数。(括号笑
函数主要过程
附解密该函数及求 x y 脚本,在壳程序的 IDA 运行
最后的解密函数比较变态,只能自己看没有啥技巧,我找到了原型代码,题目中是用的这个版本的变种,附上补丁,即可生成内置字符串的加密结果
import idaapi import struct # 壳文件的 0x41000 前2个整数 src = [0x83F08EA7, 0x3F0FBA29] # 主文件的 0x340B0 存正确结果片段,前2个整数 dst = [0x1070EC81, 0x55530000] # 枚举 y 爆破,因为反向异或 求x 的结果很大机率就是最低位字节不一样,高位一般都一样 for y in xrange(256): if (((((src[0] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[0]) & 0xFFFFFF00) == ((((src[1] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[1]) & 0xFFFFFF00)): print "y:", hex(y) break x = ((src[0] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[0] print "x:", hex(x) base = 0x441000 for i in xrange(0x5000/4): t = idaapi.get_many_bytes(base + i*4, 4) b = struct.unpack("<I", t)[0] b = ((b + 0x1010101 * y) & 0xFFFFFFFF) ^ (x + i) t = struct.pack("<I", b) idaapi.put_many_bytes(base + i*4, t)
--- Des.cpp 2017-06-22 21:29:47.000000000 +0800 +++ Des2.cpp 2017-06-22 21:45:03.000000000 +0800 @@ -6,7 +6,7 @@ */ ////////////////////////////////////////////////////////////////////////// -#include "memory.h" +#include <string.h> #include "Des.h" ////////////////////////////////////////////////////////////////////////// @@ -155,7 +155,15 @@ { static bool M[64], tmp[32], *Li=&M[0], *Ri=&M[32]; ByteToBit(M, In, 64); + if (!Type) { + for (int i=0; i<128; ++i) { + if (i % 2==0) { + M[i] = !M[i]; + } + } + } Transform(M, M, IP_Table, 64); + if( Type == ENCRYPT ){ for(int i=0; i<16; ++i) { memcpy(tmp, Ri, 32); @@ -163,7 +171,13 @@ Xor(Ri, Li, 32); memcpy(Li, tmp, 32); } + memcpy(tmp, M, 32); + memcpy(M, M+32, 32); + memcpy(M+32, tmp, 32); }else{ + memcpy(tmp, M, 32); + memcpy(M, M+32, 32); + memcpy(M+32, tmp, 32); for(int i=15; i>=0; --i) { memcpy(tmp, Li, 32); F_func(Li, (*pSubKey)[i]); @@ -172,6 +186,14 @@ } } Transform(M, M, IPR_Table, 64); + if (Type) { + for (int i=0; i<128; ++i) { + if (i % 2==0) { + M[i] = !M[i]; + } + } + } + BitToByte(Out, M, 64); } void SetSubKey(PSubKey pSubKey, const char Key[8]) @@ -220,14 +242,18 @@ } void ByteToBit(bool *Out, const char *In, int bits) { + int t = bits - 1; + if (t > 7) t = 7; for(int i=0; i<bits; ++i) - Out[i] = (In[i>>3]>>(i&7)) & 1; + Out[i] = (In[i>>3]>>(t-i%8))&1; } void BitToByte(char *Out, const bool *In, int bits) { + int t = bits - 1; + if (t > 7) t = 7; memset(Out, 0, bits>>3); for(int i=0; i<bits; ++i) - Out[i>>3] |= In[i]<<(i&7); + Out[i>>3] |= In[i]<<(t-i%8); } ////////////////////////////////////////////////////////////////////////// // Code ends at Line 231
- CreateFile 打开自身(确保是原始文件)
- VirtualAlloc 申请 0x5000 可执行 buf
- SetFilePointer seek 文件到偏移 0x41000
- ReadFile 0x5000 字节到 buf
- 将输入的前8个字符解 hex 到 uint32 x
- 将接下来两个字符解 hex 到 uint8 y
- 用 x 和 y 解密 buf 中的代码
- 用 0x4340B0 的正确代码片段 比较 buf 前96个字节
- 用 buf 中的代码解密剩余输入,结果为 内置字符 则注册成功
- 明天要早起,今天就少写点
- 我觉得这题着重考的是调试能力,我调试能力不过关,导致我根本无法调试程序开启新线程后运行的一系列逻辑,不知道咋回事,等结束去翻别人 WP
- 既然调试不了的话,我基本全程是在 IDA 上看过的,所以本文只给出程序的基本过程
- 壳程序一开始会解出一个主程序覆盖自身映射区,用仿 win 加载器内部加载后跳入入口点执行
- 只要 dump 出内存,0x400000~0x445000,先用 LordPE 修改区段物理基址和虚拟基址一致,然后用 ImportREC 填入 OEP 0x18356 即可修复导入表
- 我是无意中找到的,在分析 私有API 的 MyGetProcAddress 函数时候,发现有个字符串可疑
查找引用则找到重要函数。(括号笑
-
函数主要过程
- CreateFile 打开自身(确保是原始文件)
- VirtualAlloc 申请 0x5000 可执行 buf
- SetFilePointer seek 文件到偏移 0x41000
- ReadFile 0x5000 字节到 buf
- 将输入的前8个字符解 hex 到 uint32 x
- 将接下来两个字符解 hex 到 uint8 y
- 用 x 和 y 解密 buf 中的代码
- 用 0x4340B0 的正确代码片段 比较 buf 前96个字节
- 用 buf 中的代码解密剩余输入,结果为 内置字符 则注册成功
-
附解密该函数及求 x y 脚本,在壳程序的 IDA 运行
import idaapi import struct # 壳文件的 0x41000 前2个整数 src = [0x83F08EA7, 0x3F0FBA29] # 主文件的 0x340B0 存正确结果片段,前2个整数 dst = [0x1070EC81, 0x55530000] # 枚举 y 爆破,因为反向异或 求x 的结果很大机率就是最低位字节不一样,高位一般都一样 for y in xrange(256): if (((((src[0] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[0]) & 0xFFFFFF00) == ((((src[1] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[1]) & 0xFFFFFF00)): print "y:", hex(y) break x = ((src[0] + 0x1010101 * y) & 0xFFFFFFFF) ^ dst[0] print "x:", hex(x) base = 0x441000 for i in xrange(0x5000/4): t = idaapi.get_many_bytes(base + i*4, 4) b = struct.unpack("<I", t)[0] b = ((b + 0x1010101 * y) & 0xFFFFFFFF) ^ (x + i) t = struct.pack("<I", b) idaapi.put_many_bytes(base + i*4, t)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: