Flower花指令和壳的学习
什么是花枝令
flower是花指令,花指令是什么?其实就是插入垃圾指令,我好不容易写出的程序怎能让你这么轻易的逆出来。所以我们要通过修改汇编去破除花指令。
我们不妨想一下哪里能插入垃圾指令。你看jmp跳转以及call指令等等地方都是不二之选。
在了解花指令之前,我们先要学习ida的反汇编机制。
1 线性扫描算法,线性一条流水线上的,想想c语言的线性顺序,类比一下这就是从头到尾扫描,都解释为指令,这就使其如果遇到数据也可能错误反汇编,在反汇编代码中插入数据,反汇编就会失败。
2 递归下降算法,其根据可能执行的逻辑进行反汇编,一般是在遇到分支跳转和call指令时发挥作用,jmp指令其就不会看jmp与跳转到的地址中间的汇编代码,而例如jz等条件跳转其就会分析两条路径(跳转与不跳转)。
在介绍内容前,先看一个简单的加花的程序
1 |
|
一下汇编为
1 |
|
这就是在跳转前与后添加垃圾数据,通用的手法
讲一点前置的栈小知识
栈(stack)是自顶而下的,也就是栈顶是地址,所以压栈(push)是减去一个值,出栈是加上一个值
其遵守的是后进先出的原则
修花指令是基于栈上操作的
以下为栈图
1 | 内存高地址 |
汇编
特此声明x86汇编有很多,下面仅是部分
mov eax, immidiate(将立即数存入eax寄存器)
1 | mov eax, 2 |
push eax 将eax(32位)寄存器压栈
pop eax(将栈顶存的出栈存入eax)
1.无关花枝令
add eax,ebx(eax = eax + ebx)
sub eax, ebx (eax = eax - ebx)
mul+操作数()
nop (类似于python中的pass,空指令)
2.不定长度的指令
jmp + 标签(跳转到标签处)
1 | jmp skip ; 跳转到 skip 标签处 |
3.分支指令
xor eax,eax(eax = eax ^eax,异或是相同为0,不同为1,所以结果为0)
cmp 操作数1, 操作数2(仅影响标志位,不影响操作数,将ZF标志位相等置为1,不等置为0)
je local_3(当ZF为1,既是上面指令相等时跳转)
6.堆栈不平衡(常见于call + ret)
call指令,相当于push+jmp,先将返回地址压栈之后跳转
ret指令,相当于pop+jmp,先将返回地址出栈之后跳转
常见花指令
1 插入无关指令
例如源代码
1 | add eax, ebx |
可以插入与程序无关的指令
1 |
|
2.不定长度的指令
1 | text:0000000140001480 EB 01 jmp short label1 |
EB 00 00 00 00 00就相当于jmp下一条指令(当前地址(:0000000140001480)+2),而EB 01相当于(01 = 目标地址-当前地址-该指令的长度)
jmp 为基址+指令长度+偏移量
1 | 0000 E9 01 00 00 00 jmp 0006 |
由于线性扫描算法可能将0xE9误认为jmp,nop掉就行了
3.分支指令
由于递归下降算法,je、jne等跳转要接着往下面跳转,这样就可以在跳转指令与target地址间插入junkcode,这类解法是将无关数据nop掉
1 | xor eax,eax(自身异或一定为0) |
4.间接跳转
地址 | 指令
1 | 04009A9 call $+5 ; use '$' to get current address.'call' here is used as 'push' |
call $+5中的$表示当前地址,call会将下一个指令的地址压栈,pop rax将地址出栈存入rax
add rax,10加法指令相当于rax(04009B8) = rax(04009AE)+10,jmp rax
由于汇编时是静态的没有运行,无法解析出rax存的值,导致db 0EBh,0EBh,0EBh被错误认为为指令
解决办法从04009B8到04009B5全nop掉
5.指令复用
1 | EB FF jmp short near ptr loc_4009E0+1 ; |
这里的0xFF相当于-1(补码,有符号正数)
解决办法就是将eb nop掉
6.堆栈不平衡(常见于call + ret)
1 | xor eax,eax |
call相当于push + jmp,ret相当于pop+jmp
该段代码相当于jmp s,正常来说两个分支栈都要平衡但是
add 0x11,esp ; computer does not exec this code!
ret分支显然栈不平衡,会报错
上面不平衡的代码未执行,接着这个执行了的
1 | call next |
这相当于jmp continue:但是movl continue,esp修改了栈顶指针的指向的栈位置,ret是将continue弹出栈,但是
next仍存在栈中,这就导致栈不平衡报错
改正方法是将
call next
next:
movl continue,esp
ret
这段代码nop掉
Haruhikage
悴んだ心 ふるえる眼差し
世界で 僕は ひとりぼっちだった
散ることしか知らない春は
毎年 冷たくあしらう
暗がりの中 一方通行に
ただ ただ 言葉を書き殴って
期待するだけ むなしいと分かっていても
救いを求め続けた
(せつなくて いとおしい)
今ならば 分かる気がする
(しあわせで くるおしい)
あの日泣けなかった僕を
光は やさしく連れ立つよ
雲間をぬって きらりきらり
心満たしては 溢れ
いつしか頬を きらりきらり
熱く 熱く濡らしてゆく
君の手は どうしてこんなにも温かいの?
ねぇお願い
どうかこのまま 離さないでいて
縁を結んでは ほどきほどかれ
誰しもがそれを喜び 悲しみながら
愛を数えてゆく
鼓動を確かめるように
(うれしくて さびしくて)
今だから 分かる気がした
(たいせつで こわくって)
あの日泣けなかった僕を
光は やさしく抱きしめた
照らされた世界 咲き誇る大切な人
あたたかさを知った春は
僕のため 君のための 涙を流すよ
あぁ なんて眩しいんだろう
あぁ なんて美しいんだろう…
雲間をぬって きらりきらり
心満たしては 溢れ
いつしか頬を きらりきらり
熱く 熱く濡らしてゆく
君の手は どうしてこんなにも温かいの?
ねぇお願い
どうかこのまま 離さないでいて
ずっと ずっと 離さないでいて [10
