【reverse】逆向6 JCC
【reverse】逆向6 JCC
前言
我們之前學習的時候講了,eip暫存器儲存的是當前(即將執行的語句的) 指向地址
而我們之前提到的下斷點(F2),就和我們程式設計中的下斷點一樣,執行到某句彙編指令然後停住
今天的課程的別名又叫作《修改eip》
1、JMP指令
JMP指令的作用類似於mov的作用,只不過mov不用用於eip暫存器,我們要通過jmp指令來操作eip暫存器
並且JMP指令只能作用於eip暫存器
如果我們跳轉的位置距離當前位置小於128個位元組,會加上short的關鍵字
如果大於128那麼就不會寫
JMP發生作用的時候,只會作用與eip暫存器
舉個例子
這個時候,我們的eip儲存的記憶體地址為
我們執行一下jmp指令,發現eip儲存的記憶體地址為我們jmp的記憶體地址
2、CALL指令
call指令也會讓eip跳轉到想去的地址,但是call和jmp的區別就是,call跳轉的時候,會將call到了ret時候下一個執行的彙編命令的地址存入堆疊中
舉個例子
我們call(call到00401006)
call之前的eip和esp
call之前的堆疊
我們執行一下call指令(在00401006這裡下斷點)
執行完之後發現esp(棧頂)的地址-4,也就是堆疊存了一個4位元組的資料,eip的地址跑到了我們call的地方
我們來看看堆疊儲存的資料,儲存了一個返回地址,這個地址是根據我們第一張圖可以知道,是call語句之後的下一條語句
然後我們再再00401006上彙編一條retn語句
我們執行一下
發現我們的esp和eip也變了,esp的地址+4,說明pop了剛剛儲存的返回地址,eip指向的就是剛剛的返回地址
我們看看堆疊的變化
堆疊當前的指標指向0019ff74,pop了上面的0019ff70
這就是call和retn的功能,retn的作用其實就相當於是pop eip,只不過不允許這麼寫
我們在用正向程式碼執行函式的時候,其實就是不斷的儲存返回地址到堆疊中,然後執行函式的功能,最後retn到原來的記憶體地址上
3、CMP指令
指令格式
cmp R/M,R/M/IMM
該指令是比較兩個運算元,實際上,它相當於sub指令,但是相減的結構並不是儲存到第一個運算元中
只是根據相減的結果來改變標誌位的,當兩個運算元相等的時候,ZF = 1
所以cmp的作用就是sub的作用而不該暫存器的值,僅僅是改變標誌暫存器
cmp一般用於比較兩個數是否相等
同時,我們可以觀察SF位,如果SF = 1,那麼說明第一個資料比第二個資料小,反之成立
當然cmp不僅僅可以比較兩個通用暫存器,同時也可以比較暫存器和一塊記憶體地址儲存的資料(前提是 資料寬度一樣)
cmp eax,ecx
cmp eax,dword ptr ds:[405000]
我們進行一個測試
首先給eax和ecx分別賦值0x1和0x2,然後給所有的標誌暫存器置0
然後執行cmp彙編指令,標誌暫存器結果如下
cf = 1因為0x1-0x2產生了借位
pf = 1因為得到的結果是ffff ffff,最低有效位元組是ff,換成2進位制,1111 1111,有偶數個1,所以置1
af = 1因為輔助位借位了
zf = 0因為相減結果是ffff ffff不為0
sf = 1因為符號位是1
of = 0 因為沒有溢位
4、TEST值指令
指令格式:
TEST R/M,R/M/IMM
該指令在邏輯程度上和CMP指令類似,兩個數值進行 與 操作,結果不儲存,僅僅改變標誌位
常見用法:
判斷某個暫存器是否等於0
# 判斷eax是否存值為0
test eax,eax
舉個例子
我們把eax置0,把標誌位暫存器全部置0
然後執行彙編
得到結果如下
cf = 0 因為與運算沒有進位或借位
pf = 1 因為結果結果為0000 0000,最低有效位元組是00,有0(偶數)個1,所以為1
af = 0 因為與運算沒有進位或借位
zf = 1 因為結果為0
sf = 0 因為符號位就是0
of = 0 因為沒有溢位
5、JCC
JCC說白了就是不同情況下的jmp,根據標誌暫存器來跳轉
先理解,然後背誦
JCC只與符號標誌位有關,不影響堆疊、不影響暫存器
JE、JZ
je = jump if equal
jz = jump if zero
ZF = 1 跳轉
結果為0則跳轉(相等時跳轉)
JNE、JNZ
jne = jump if not equal
jnz = jump if not zero
ZF = 0 跳轉
結果不為0則跳轉(不相等時跳轉)
JS
js = jump if SF
SF = 1 跳轉
結果為負數則跳轉
JNS
JNS = jump if not SF
SF = 0 跳轉
結果為正數則跳轉
JP、JPE
JP = jump if PF
JPE = jump if even (偶數)
PF = 1 跳轉
結果中最低有效位元組中1的個數為偶數則跳轉
JNP、JPO
JNP = jump if not PF
JPO = Jump if odd(奇數)
PF = 0 跳轉
結果中最低有效位元組中1的個數為奇數則跳轉
JO
JO = jump if OF
OF = 1 跳轉
有溢位就跳轉
JNO
JNO = jump if not OF
OF = 0 跳轉
沒有溢位就跳轉
JC、JB、JNAE
存jump if carry;jump if below;jump if not above equal
一般是與cmp一起用
mov ax,2
cmp ax,3 # 比較ax的值和3
jb next # 小於就轉到next
大於則跳轉(無符號數)
CF = 1跳轉
JNC、JNB、JAE
jump if not carry;jump if not below;jump if above equal
大於等於則跳轉(無符號數)
CF = 0 跳轉
JBE、JNA
jump if below equal;jump if not above
小於等於則跳轉(無符號數)
CF = 1 or ZF =1
JNBE、JA
jump if not below equal;jump if above
大於則跳轉(無符號數)
CF = 0 and ZF = 0
JL、JNGE
jump if less;jump if not greater equal jump
小於則跳轉(有符號數)
SF != OF
JNL、JGE
jump if not less;jump if greater equal
大於等於則跳轉(有符號數)
SF = OF
JLE、JNG
jump if less equal;jump if not greater
小於等於則跳轉(有符號數)
ZF = 1 or SF != OF
JNLE、JG
jump if not less equal;jump if greater
大於則跳轉(有符號數)
ZF = 0 and SF = OF
6、JCC總結
JCC指令 | 中文含義 | 英文原意 | 檢查符號位 | 典型C應用 |
---|---|---|---|---|
JZ/JE |
若為0則跳轉;若相等則跳轉 | jump if zero;jump if equal | ZF=1 |
if (i == j);if (i == 0); |
JNZ/JNE |
若不為0則跳轉;若不相等則跳轉 | jump if not zero;jump if not equal | ZF=0 |
if (i != j);if (i != 0); |
JS |
若為負則跳轉 | jump if sign | SF=1 |
if (i < 0); |
JNS |
若為正則跳轉 | jump if not sign | SF=0 |
if (i > 0); |
JP/JPE |
若1出現次數為偶數則跳轉 | jump if Parity (Even) | PF=1 |
(null) |
JNP/JPO |
若1出現次數為奇數則跳轉 | jump if not parity (odd) | PF=0 |
(null) |
JO |
若溢位則跳轉 | jump if overflow | OF=1 |
(null) |
JNO |
若無溢位則跳轉 | jump if not overflow | OF=0 |
(null) |
JC/JB/JNAE |
若進位則跳轉;若低於則跳轉;若不高於等於則跳轉 | jump if carry;jump if below;jump if not above equal | CF=1 |
if (i < j); |
JNC/JNB/JAE |
若無進位則跳轉;若不低於則跳轉;若高於等於則跳轉; | jump if not carry;jump if not below;jump if above equal | CF=0 |
if (i >= j); |
JBE/JNA |
若低於等於則跳轉;若不高於則跳轉 | jump if below equal;jump if not above | ZF=1或CF=1 |
if (i <= j); |
JNBE/JA |
若不低於等於則跳轉;若高於則跳轉 | jump if not below equal;jump if above | ZF=0或CF=0 |
if (i > j); |
JL/JNGE |
若小於則跳轉;若不大於等於則跳轉 | jump if less;jump if not greater equal jump | SF != OF |
if (si < sj); |
JNL/JGE |
若不小於則跳轉;若大於等於則跳轉; | jump if not less;jump if greater equal | SF = OF |
if (si >= sj); |
JLE/JNG |
若小於等於則跳轉;若不大於則跳轉 | jump if less equal;jump if not greater | ZF != OF 或 ZF=1 |
if (si <= sj); |
JNLE/JG |
若不小於等於則跳轉;若大於則跳轉 | jump if not less equal;jump if greater | SF=0F 且 ZF=0 |
if(si>sj) |