csapp 第十二章 并发编程
ez_byte
首先我们先打开文件运行一下,看一下输入和输出。进去就是输入,输入之后会对我们的输入进行回显,没有什么非常关键的信息。
打开ida进行分析,main函数没有什么发现
我们跳到数据区,发现这个100%下面的,yes并没有在string窗口出现,我们按下x查询交叉引用,在执行yes之前,有个jmp指令,也就是说,按照程序执行是永远不好去到yes的地方的,也就是说,一定有什么操作,然后再跳到yes中去。
我们patch一下jmp,将其修改为条件跳转,看看具体是操作。
我们查看判断跳入,yes的汇编,我们可以发现,
有个判断r12是否为零,但是并没有出现对r12的任何操作,说明我们想要的操作被隐藏起来了。
分析函数,我们可以查看到这样一个函数,一个异常处理函数
void __noreturn sub_404BF5(){_DWORD *exception; // rax
exception = (_DWORD *)_cxa_allocate_exception(4LL);
*exception = 1;
_cxa_throw(exception, &off_5CB8C8, 0LL);}
fenter里会有一系列SSE指令集有关xmm寄存器操作
对于异常处理
C++异常处理机制(throw、try、catch、finally) - 知道了呀~ - 博客园 (cnblogs.com)
c++ 异常处理(1) - twoon - 博客园 (cnblogs.com)
c++ 异常处理(2) - twoon - 博客园 (cnblogs.com)
为此,我们可以大致猜测就是运行程序,触发一个异常,然后通过此条转到想要操作的地方,进行操作,通过题目描述,应该就是嵌入了一堆字节码。
通过查阅资料,有个大佬写了关于此方面的知识。
通过DWARF Expression将代码隐藏在栈展开过程中-软件逆向-看雪-安全社区|安全招聘|kanxue.com
当触发异常的时候,程序会沿着调用链不断向上进行栈展开,直到寻找到能处理这个异常的catch块。
然而在这个过程中DWARF调试信息完成这个恢复过程
而在DWARF 3标准中引入了一个DWARF Expression,这个WARF Expression变相就是一个虚拟机。
到此,我们大致就可以知道,我们的操作就是被隐藏在了这个栈展开中DWARF的“虚拟机”字节码中,
在Linux中我们执行readelf -Wwr ezbyte > out.txt,将DWARF 调试信息打印出来
在前面,我们分析了,对r12的操作,并没有直接出现在代码上,操作代码被隐藏了。这里我们在文件中,搜索r12,发现在这里对我们的r12进行了操作,并且这也“虚拟机”字节码的操作部分。
DWARF Debugging Information Format Version 5 (dwarfstd.org)
通过官方文档,查询执行操作的命令
整个的操作思路
DW_OP_constu: 8722213363631027234:将一个无符号整数压入堆栈。
DW_OP_constu: 1890878197237214971:将另一个无符号整数压入堆栈。
DW_OP_constu: 9123704:将第三个无符号整数压入堆栈。
DW_OP_breg15 (r15): 0:从 r15 这个寄存器中读取一个值,并将其加上偏移量 0。
DW_OP_plus:从堆栈中弹出两个值,相加后再将结果压入堆栈。
DW_OP_xor:从堆栈中弹出两个值,进行异或运算后再将结果压入堆栈。
DW_OP_xor:重复前面的操作,再进行一次异或运算。
DW_OP_constu: 2451795628338718684:将另一个无符号整数压入堆栈。
DW_OP_constu: 1098791727398412397:将另一个无符号整数压入堆栈。
DW_OP_constu: 1512312:将第三个无符号整数压入堆栈。
DW_OP_breg14 (r14): 0:从 r14 这个寄存器中读取一个值,并将其加上偏移量 0。
DW_OP_plus:从堆栈中弹出两个值,相加后再将结果压入堆栈。
DW_OP_xor:从堆栈中弹出两个值,进行异或运算后再将结果压入堆栈。
DW_OP_xor:重复前面
分析完毕之后,写出我们的脚本
def decrypt():
r15 = (8722213363631027234 ^ 1890878197237214971) - 9123704
r14 = (2451795628338718684 ^ 1098791727398412397) - 1512312
r13 = (8502251781212277489 ^ 1209847170981118947) - 8971237
r12 = (2616514329260088143 ^ 1237891274917891239) - 1892739
print(hex(r12))
print(hex(r13))
print(hex(r14))
print(hex(r15))
import binascii
hexstring = "65363039656662352d653730652d346539342d616336392d6163333164393663"
print("flag{" + binascii.unhexlify(hexstring).decode(encoding="utf-8") + "3861}")
# print(binascii.unhexlify(hex(r15)[2:]).decode('utf-8'), end='')
# print(binascii.unhexlify(hex(r14)[2:]).decode('utf-8'), end='')
# print(binascii.unhexlify(hex(r13)[2:]).decode('utf-8'), end=' ')
# print(binascii.unhexlify(hex(r12)[2:]).decode('utf-8'), end=' ')
decrypt()
解出flag: flag{e609efb5-e70e-4e94-ac69-ac31d96c3861}