-
-
[原创] 第六题 寻回宝剑 writeup
-
2021-5-19 15:33 5691
-
拖入IDA分析,可以看到大量结构类似的重复指令,调试可以看出这部分的作用是跳转到下一条指令。
可以使用idapython清除来接近程序原本的面目。
def patch(): startAddr = 0x140001000 endAddr = 0x1400FA68A i = startAddr print (hex(startAddr),hex(endAddr)) while i <= endAddr: addr = i addr1 = next_head(addr) addr2 = next_head(addr1) addr3 = next_head(addr2) addr4 = next_head(addr3) addr5 = next_head(addr4) addr6 = next_head(addr5) addr7 = next_head(addr6) addr8 = next_head(addr7) addr9 = next_head(addr8) addr10 = next_head(addr9) if idc.GetDisasm(addr) == 'push rax' \ and idc.GetDisasm(addr1) == 'push rax' \ and idc.GetDisasm(addr2) == 'pushfq' \ and idc.GetDisasm(addr3) == 'call $+5' \ and idc.GetDisasm(addr4) == 'pop rax' \ and idc.GetDisasm(addr5).find('xor rax,') != -1 \ and idc.GetDisasm(addr6).find('mov ') != -1 \ and idc.GetDisasm(addr7) == 'popfq' \ and idc.GetDisasm(addr8) == 'pop rax' \ and idc.GetDisasm(addr9) == 'retn': addrj = (addr4 ^ idc.get_operand_value(addr5,1)) - addr4 addrptch = addr while(addrptch < addr3): patch_byte(addrptch,0x90) addrptch = addrptch + 1 patch_byte(addr3,0xE9) patch_dword(addr3+1,addrj) addrptch = addr4 while(addrptch <= addr9): patch_byte(addrptch,0x90) addrptch = addrptch + 1 i = next_head(addr9) elif idc.GetDisasm(addr) == 'push rax'\ and idc.GetDisasm(addr1) == 'pop rax': addrptch = addr while(addrptch <= addr1): patch_byte(addrptch,0x90) addrptch = addrptch + 1 i = next_head(addr1) elif idc.GetDisasm(addr) == 'push rbx'\ and idc.GetDisasm(addr1) == 'pop rbx': addrptch = addr while(addrptch <= addr1): patch_byte(addrptch,0x90) addrptch = addrptch + 1 i = next_head(addr1) elif idc.GetDisasm(addr) == 'push rcx'\ and idc.GetDisasm(addr1) == 'pop rcx': addrptch = addr while(addrptch <= addr1): patch_byte(addrptch,0x90) addrptch = addrptch + 1 i = next_head(addr1) elif idc.GetDisasm(addr) == 'push rdx'\ and idc.GetDisasm(addr1) == 'pop rdx': addrptch = addr while(addrptch <= addr1): patch_byte(addrptch,0x90) addrptch = addrptch + 1 i = next_head(addr1) else: i = next_head(addr)
清除后动态调试分析,在以下可能的导入函数下段。
最开始会和1746(即36*49结果)比较,相等的话会提示错误。
然后取输入的长度,如果不等于84则也提示错误。
判断输入字符在0~9,A~Z,+-*/%=这42个字符内,索引为0~41。
输入的字符两两为一组,一共42组转换成数值表(第一位*42 + 第二位),后面的数字不能比前面的小,所以推断出格式应每组数第一位肯定是不能减小的。
然后会判断使用数值表的数依次与42取商取余(第一位索引即为商,第二位索引即为余)不重复,即可推断出第一位数字应该不相同的,递增的,为0_ 1_ 2_ ……/_%_=_,每组数的第二位也是不同的。
按照以上规则输入(001122…//%%==),也还是有问题的,进一步分析可得:依次使用数值表后面(第二位,第三位。。。)与42商余减第一位,得到一个组成一个二维表,使用(第三位,第四位。。。)与42商余,得到一个组成一个二维表。。。依次到最后,所有的二维表不能重复。并且由于第一位数是递增的,可由此推断,第二位索引两两相距位置相同的数字之差不能有重复。这样如果用来跑结果的话数据量还太大。
按照以上规则输入(001122…//%%==),跳过其中的检查,会到后面一步有比较,可以得到正确的码的前28位(02152S3X4Z5Q6C7T819/ADB%C*DL)。这样的话前面固定,就可以写程序来跑后面的结果了。
程序如下:
class Program { static string chartable = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%="; public static bool IsRepeat(int[] array) { Hashtable ht = new Hashtable(); for (int i = 0; i < array.Length; i++) { if (ht.Contains(array[i])) { return true; } else { ht.Add(array[i], array[i]); } } return false; } public static bool Test(int[] xxx) { bool flag = true; for (int i = 0; i < xxx.Length - 1; i++) { int[] xxxx = new int[xxx.Length - i - 1]; for (int j = 0; j < xxx.Length - i - 1; j++) { xxxx[j] = xxx[j + i + 1] - xxx[j]; } if (IsRepeat(xxxx)) { flag = false; break; } } if (flag) { return true; } else { return false; } } static void Guess(int[] now,int[] nothave) { int have = now.Length - nothave.Length; int[] test = new int[now.Length + 1]; Array.Copy(now, 0, test, 0, now.Length); foreach (var item in nothave) { test[test.Length - 1] = item; if (Test(test)) { if (nothave.Length -1>0) { int[] nothave2 = new int[nothave.Length - 1]; int index = 0; for (int i = 0; i < nothave.Length; i++) { if (test.Contains(nothave[i])) { continue; } else { nothave2[index++] = nothave[i]; } } Test4(test, nothave2); } else { if (Test(test)) { foreach (var item1 in test) { Console.Write(item1 + ","); } } } } else { continue; } } } static void Main(string[] args) { int[] now = new int[14] { 2, 5, 28, 33, 35, 26, 12, 29, 1, 39, 13, 40, 38, 21 };//每组第二位 int[] nothave = new int[28] { 0, 3, 4, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 30, 31, 32, 34, 36, 37, 41 }; Guess(now , nothave); } }
跑的结果:
02152S3X4Z5Q6C7T819/ADB%C*DLEIFUG3HRIHJ6K7L0MBNKOJPPQ=RNS+TEUOVWWGXYYMZ9+4-8*F/-%V=A
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界