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


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

 

一丶LOOP指令(循環指令)

作用:

  循環指令利用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了

1.最原始的Call

主程序調用子程序的流程示意圖:

  

這里主要介紹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 了,根本就不通用,怎么辦,而且如果調用多次怎么辦,

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

2.Call 帶有參數的傳遞

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

看代碼:

  

mov cx,1
mov dx,1
jmp 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個,我們的寄存器都不夠用了怎么辦

3.更高級的Call帶參數

  我們這個時候就會想到,寄存器已經不能滿足我們的需求,這個時候,可以使用棧,我們可以使用棧來保存信息

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

mov cx,2
    push cx             ;壓棧
    mov dx,1
    push dx        ;調用函數
    CALL PROC_ADD    
    mov dl,al
    mov ah,2h       ;執行顯示al內容
    int 21h
    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

需要注意的是,ret只會把最后壓入的返回地址返回,但是參數還沒有平棧,只能在調用完畢之后,在返回地址出的下一條指令自己平棧

4.Call的詳細調用

mov cx,1
push cx
mov bx,2
push 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,所以就有了花指令去除工具

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

 學習資料鏈接: http://pan.baidu.com/s/1slHi4vN 密碼:hvjp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM