patch二进制文件的那些事
本文最后更新于:1 个月前
话说BUU上的这道题,我第一次自己做的时候也无异于网上诸多的解法
进行反编译代码分析,在get_flag()函数中比较直观地能发现,按正常应该是判断条件先为4,将f2进行一个初始赋值(追加)操作,然后判断条件为5,对f2进行一定的逻辑变化,最后判断条件再为1,输出flag
f1已经可以得知,于是重点就放在了f2上面
按照题目逻辑我写下了下述破解f2的小脚本:
1 |
|
但是只有这一种方式吗?
后面尝试过一些简单的小patch后,再回来看这道题,我也打算通过这种方式来完成它
patch方案不难想到,既然我们需要判断条件按照4、5、1的顺序输出,那我们改一下他们的跳表就行了
判断条件switch(rand() % 200)
怎么改?这不是有个现成的循环变量i
可以用嘛.jpg
看汇编代码,下面这一段正式switch(rand%200)
的逻辑,rand()%200的值存放在了[rbp+var_34]
中,并加载到了eax寄存器中
这三行代码为switch的关键
rax*8是由于一段地址长8字节,乘以8之后将跳表中对应条件值的地址赋值给rax,最后再jmp到rax
eax是rax的低32位,所以此处rax*8是获取前面存入rax寄存器的值,即rand()%200
的返回值
那么这里就非常明显了,将此处的[rbp_var_34]
改为i即可
i的地址ida中已经很贴心地帮我们写出来了
所以此处我们如此patch
反编译回去,发现此处条件已经变为了i
下一步就是要对跳表操刀了
我们到跳表jpt_400843
的位置,可以看到几个条件对应的地址了
loc_400845对应的case 1
loc_4008A2对应的case 2
loc_4008B6对应的case 3
loc_4008CA对应的case 4
loc_400909对应的case 5
因此这里我们只需要稍微改下前面提到的三个条件的顺序,让他们按照前面提到的顺序出现就行
更直观点,在跳表处按ctrl+tab来到hex视图,每8个字节就是一块地址,我们只需要修改对应的字节即可
我们试着调换一下CA和45的位置
成功更换了二者的位置!
下一步只需要把此时的case4和case5调换下位置即可
然后就出问题了,,没截下图来,是一个JUMPOUT的问题,并且逻辑也并不按照预期来
后面菜菜师傅给我提供了一个很棒的思路
直接按照预期的顺序依次jmp过去就行了
将case4中原本的break的jmp的目标地址改成case5的
成功
但是在将case5的break改成jmp到case1的起始地址就出问题了
此时patch界面爆红,什么意思呢?
实际上因为跳转地址超出short的范围而原本使用的是短跳指令jmp short导致的
原本的语句是:jmp short loc_400975 ; EB 0A
,指令占2字节空间
但是jmp loc_400845 ; E9 XX XX XX XX
是 near jump,占5字节,导致下面原本正常的语句会被覆盖,导致出错