0ctf2017-pages-choices
Pages
题目来自于CCS 2016 《Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR》,利用intel prefetch指令来区分mmaped memory和empty memory。
Choices
想找时间再分析分析这个题目然后再把writeup给写了,但是感觉最近没空,就先把这个发了。
这是一个被控制流混淆的逆向题目,还好原来的程序不是很复杂,混淆后也将就能看。程序提供了被混淆的程序本身,也提供了混淆这个程序的Clang插件,并告诉Clang的版本是3.9.1。自己并没有分析清楚这个控制流是怎么混淆的,只是通过一些其他手段分析出flag。
程序的基本功能是用户不断的输入数字,直到用户输入-1173196446的时候程序开始计算一段内存的sha256的数值,如果和指定的值匹配,则这段内存就是flag并输出。程序会根据用户的输入数字进行具体的操作,操作有三种:第一种是根据index取指定地址的数据,每次取4字节(这段数据在程序的.rodata节,长度为56字节,index初始值为0);第二种是对取出的数据进行运算;第三种是将运算后的数据放到指定缓冲区(就是flag缓冲区),并增加index为下一次取数据做准备。到最后则计算缓冲区的sha256并验证。
如果用户输入的数字没有落到这三种当中,则一直输入下去。根据对三种操作的分析,则第一种和第三种是配对的,中间可以插入任意多个第二种操作。而且,为了能通过验证,则用户输入的数字序列应该是唯一的。
自己尝试使用提供的命令行来编译自己写的程序来观察这个插件的工作,不幸的是并没有编译成功。因为这个插件的两个导入函数在其他模块,而其他模块并没有被提供。分别是toObfuscate(bool, llvm::Function*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)和fixStack。
将提供的Clang插件拉入IDA,可以定位到关键函数就是Oops::OopsFlattening::runOnFunction,大致的分析后发现程序在用户的程序中插入scanf调用,而且在进行分支处理的时候会调用Oops::CryptoUtils::scramble32(Oops::CryptoUtils *this, unsigned int id, const char *data)获取一个32位的数值,id则是从0开始增加代表分支的label id。结合程序里的各种数字,我推断将id从0开始递增不断调用Oops::CryptoUtils::scramble32的返回值序列将是正确的输入序列,验证之后确实如此。在分析了Oops::CryptoUtils::scramble32之后,发现函数的返回值与data字符串内容有关。
将程序的缺少的两个导入函数的调用给nop掉,然后就可以用gdb调试clang的编译过程了,在Oops::OopsFlattening::runOnFunction上下断点,跟下去就能获得data的数值,接下来用idaemu模拟执行Oops::CryptoUtils::scramble32获取正确的输入序列。核心的代码:
1 def getrandom(emu): 2 randoms = [] 3 buf = '\x4b\x45\x10\x20\x8d\xc5\xf9\xb6\x61\xd6\xcf\x32\x12\x44\xd1\x3e' 4 rrdx = 0xc0000000 5 emu.setData(rrdx, buf) 6 for i in range(100): 7 rax = emu.eFunc(0x27934, args=[0, i, rrdx]) 8 randoms.append(rax) 9 #end 10 if rax == 0xba127162: 11 break 12 return randoms 13 def getinput(rands): 14 input = '' 15 for i in rands: 16 if i < 0x80000000: 17 input += str(i).strip('L') 18 input += ' ' 19 else: 20 input += '-' 21 input += str(0x100000000-i).strip('L') 22 input += ' ' 23 input += 'done' 24 return input 25 emu = Emu(UC_ARCH_X86,UC_MODE_64) 26 rands = getrandom(emu) 27 input = getinput(rands) 28 #print(rands) 29 print(input) 30 del emu
input就是-31433233 -285567292 2037610950 -2095442962 1882077595 899592143 -1232084351 -1035247152 -673337996 362736264 -1818931825 1163875799 1309929227 -1304292073 -555122902 -924598566 -1618250207 1890769795 -972048612 302076013 49850286 1301200376 1815301527 -1465217760 -41945993 -1114108749 971973067 -526488978 -1190177184 1886727646 -1139056370 -502439399 510890680 301250227 -1966906358 -468320086 -1117675870 -278521534 842536262 80078663 -1403901587 1264512961 -135592801 1089631664 2125370169 -2083050856 803195994 68351607 -382958238 1144688074 -194893474 -1391846984 -928154047 -292497767 2102294064 -164926706 883886221 -594992301 755772664 -807924817 -77124306 1847175114 -1173196446 done。Flag就是flag{wHy_d1D_you_Gen3R47e_cas3_c0nst_v4lUE_in_7h15_way?}