1. 程式人生 > 其它 >【reverse】逆向6 JCC

【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)