16位彙編第九講彙編指令以及逆向中的花指令

2021-08-07 22:38:30 字數 3587 閱讀 2967

作用:

迴圈指令利用cx計數器自動減1,方便實現計數迴圈的程式結構

例如:

mov cx,3   

loop1:    ;標號

.....

loop loop1;不斷的迴圈標號,然後cx-- 直到變為零

每次迴圈過後,cx都會自減,直到cx == 0,不過現在的loop指令不常用了,因為侷限性太大,比如loop只能自減,而不能自增,所以我們都用 jcc 指令,來模擬loop指令

問題? 什麼是子程式

1.子程式是完成特定功能的一段程式

2.當主程式(呼叫程式)需要執行這個功能的時候,採用call呼叫指令轉移到改子程式的起始處執行

3.當執行萬子程式的功能的時候,採用 ret 返回指令回到主程式繼續執行

如果懂c語言或者別的更高階的語言的請看

這個其實就是函式,為了**的重用性,可利用性研究出來的,否則彙編**一多就會很亂,比如有效的管理**

比如ret指令,其實就是平衡棧的,在c語言中變成了語法,為return了

主程式呼叫子程式的流程示意圖:

這裡主要介紹call傳參,以及使用ret

call的原理是什麼?

首先先看一段匯程式設計序

jmp proc_add           ;跳轉到函式執行
d_one: jmp end_exit   ;跳轉到程式結束位置,結束程式 

proc_add:;函式add方法

mov ax,1

mov bx,1

add ax,bx ;ax和bx相加,結果儲存到ax中,ax當做返回值返回

jmp d_one ;跳轉到 函式執行後的嚇一嚇一跳指令繼續執行

end_exit: ;程式結束的**不關注

mov ax,

4c00h int 21h

看到上面的**發現了什麼,是不是和我們上面的圖很像

主程式 -> 子程式的add方法, 然後 -> 跳轉回來,跳轉到下一條指令繼續指令

這個就是雛形了,但是你有沒有想過,這個add只能實現1 + 1 了,根本就不通用,怎麼辦,而且如果呼叫多次怎麼辦,

一直加標號,一直呼叫嗎,顯然是不切實際的.

上面發現了乙個大缺陷,就是不能引數傳遞,這樣就不行了,那麼我們要想辦法,可不可以在外面傳入引數

看**:

mov cx,1

mov dx,

1jmp proc_add ;跳轉到函式執行

d_one: jmp end_exit  ;跳轉到程式結束位置,結束程式

proc_add: ;函式add方法

mov ax,cx ;改為cx

mov bx,dx ;改為dx

add ax,bx ;ax和bx相加,結果儲存到ax中,ax當做返回值返回

jmp d_one ;跳轉到 函式執行後的嚇一嚇一跳指令繼續執行

end_exit: ;程式結束的**不關注

mov ax,

4c00h

int 21h

我們發現,在外部暫存器更改了,就可以修改引數了,但是還有問題,暫存器一共才多少個,當我們引數有10個怎麼辦

比如createprocess api,它的引數就有10個以上,不用關心api是幹啥的,可以看下引數.

正好10個,我們的暫存器都不夠用了怎麼辦

我們這個時候就會想到,暫存器已經不能滿足我們的需求,這個時候,可以使用棧,我們可以使用棧來儲存資訊

出棧的時候棧平衡(就是使棧空間不被破壞)一下

mov cx,2

push cx ;壓棧

mov dx,

1push dx        ;呼叫函式

call proc_add

mov dl,al

mov ah,2h       ;執行顯示al內容

int21h

jmp end_exit

proc_add:

mov bp,sp

mov ax,[bp +2]      ; 從棧中取出內容,注意為什麼+2

mov bx,[bp+ 4]

add ax,bx

ret

在這裡應該注意到了,我們用call呼叫的時候,為什麼函式內部要+2

原因是當這個子程式執行完畢的時候,需要返回到主程式執行,所以主程式的下一條指令已經壓棧了,所以+2位置,可以取得引數

最後呼叫ret平棧

當程式遇到ret的時候,做的事情

1. 首先修改ip的值,ip的值, =  (ss棧段暫存器) * 16 + (sp棧頂)的值,

2.(sp棧頂) = (sp棧頂) + 2

mov cx,1

push cx

mov bx,

2push bx

call proc_add

proc_add:

......

ret

ret的作用,就是從棧棧中取出返回位址,然後賦值給ip繼續執行嚇一條指令

但是注意,這裡並沒有平棧,我們必須在外面自己平棧

比如,我們我們入棧兩個引數,比如  add sp,4   讓sp平棧

請看下面的彙編**

我們發現jmp的地方下面申請了乙個位元組,但是在彙編的時候,這1個位元組和mov的機器碼在一起了

因而產生的彙編**就出錯了,花指令混淆就是這樣,這段**還是可以正常執行的

對抗手法

1.如果是動態的除錯,那麼花指令是沒用的(動態除錯就是一步一步走)為什麼,因為為了保證彙編**不出錯

每走一次**都會重新反彙編

2.花指令主要對抗的是靜態除錯,因為病毒是不能執行的,只能看二進位制和彙編,這個時候怎麼辦

我們發現了,他要jmp, jmp 1個位元組,這個時候可以寫個工具去弄,把jmp變為nop(就是告訴cpu不執行)

現在我們在winhex中找到,然後改為 90機器碼(代表nop)

修改的時候,先看下反彙編 找到01的地方,改為90則nop掉了,那麼正確的反彙編就出現了

然後發現花指令去除了,這個就是最簡單的花指令,當然這個可以通過尋找jmp的跳轉的位元組數,把裡面的內容依次修改為nop,所以就有了花指令去除工具

注意,這裡是最簡單的花指令,還有更複雜的,道高一尺魔高一丈,所以沒有完整的花指令去除工具,到最後,可能你需要自己去分析,自己去修改了.

16位彙編第一講簡介

組合語言他是計算機語言,計算機語言通俗點說就是人類和計算機 也就是cpu 溝通的橋梁,計算機不認識人類的語言,只認得二進位制 0和1 但是我們想讓你算計完成我們的工作,每次都是0,和1,那樣會崩潰的,老一輩的是這樣的 所以後面組合語言出現了,用一些簡單的助記符來替代機器語言 二進位制 通用的語言,比...

16位彙編第六講 8086指令集(2)

掌握 add adc inc sub sbb dec neg cmp 熟悉 mul imul div idiv 理解 cbw cwd daa das aaa aas aam aad add reg,imm reg mem reg reg imm reg mem add mem,imm reg mem...

16位彙編第七講 8086指令集(3)

cbw al的符號擴充套件至ah 如al的最高有效位是0,則ah 00 al的最高有效位為1,則ah ffh。al不變cwd ax的符號擴充套件至dx 如ax的最高有效位是0,則dx 00 ax的最高有效位為1,則dx ffffh。ax不變符號擴充套件的概念 符號擴充套件是指用乙個運算元的符號位 即...