1. 程式人生 > >PC逆向之程式碼還原技術,第四講彙編中減法的程式碼還原

PC逆向之程式碼還原技術,第四講彙編中減法的程式碼還原

目錄

PC逆向之程式碼還原技術,第四講彙編中減法的程式碼還原

一丶彙編簡介

在講解減法的程式碼還原之前.我們首先要知道. 減法在彙編中對應的指令是什麼.
Sub 彙編指令. Sub x,y 將x的值 加上y 並且重新賦值給x

二丶高階程式碼對應彙編觀看.

觀看如下程式碼

int main(int argc, char* argv[])
{
    int nValue = 10 - 2;        //常量 - 常量 給變數
    int nVar = nValue - 10;     //變數 - 常量
    int nVar3 = nValue - nVar;  //變數 - 變數
    nVar3 = nValue - -5;        //變數 - 負數常量

    return 0;
}

有四種方式
第一種 常量 - 常量
第二種 變數 - 常量
第三種 變數 - 變數
第四種 變數 + 負數常量

1.程式碼還原解析:

程式碼還原解析需要了解的知識:

reg: 代表任意通用暫存器
imm: 立即數,可以看做常量
? : 代表任意數值.可以 [ebp -?]可以確定那個變數,變數是在棧中存放的.

  • 第一種方式 常量 - 常量
    常量-常量 在編譯器編譯的時候. 優化的時候直接就已經計算出來了. 所以常量- 常量就是固定的值了.
    如果給變數則會使用mov指令將常量賦值給變數.

  • 第二種方式 變數 -常量
    變數 - 常量 .我們首先要知道.變數在彙編的角度來說.就是在棧中記憶體儲存的. 而棧 - imm(立即數)
    在湖邊中沒有這種指令
    例如:
    sub [ebp - ?],10
    所以只要操作變數必然會操作一個暫存器進行操作.
    所以會產生以下程式碼定式:
mov reg,[ebp - ?]  獲得變數值
sub reg,imm        用暫存器相減
mov [ebp - ?],reg  重新將暫存器的值賦值給某變數.
  • 第三種方式 變數 - 變數
    變數- 變數 我們通過第二種方式可以得知.操作變數的時候必然會使用暫存器.此時有兩個變數.
    那麼會不會操作兩個暫存器?
    答: 不會操作兩個暫存器. 彙編中支援 暫存器的值 跟 棧中記憶體的值 互相操作.

產生的程式碼定式:

mov reg,[ebp - 4]  獲得第一個變數的值
sub reg,[ebp - 8]  reg - 第二個變數的值. 結果給reg儲存
mov [ebp - c[,reg  將結果利用mov賦值指令賦值給變數三.
  • 第四種方式 變數 - 負數
    首先操作了變數.那麼肯定會操作暫存器. 而 - 負數 在數學中 負負得正. 所以負數在彙編中會被加上
    所以產生程式碼定式:
mov reg,[ebp - 4];
add reg,|負數|        |負數|  這個代表負數的絕對值
mov [ebp - 8], reg

三丶根據高階程式碼IDA反彙編的完整程式碼


.text:00401250 _main_0         proc near               ; CODE XREF: _main↑j
.text:00401250
.text:00401250 var_4C          = byte ptr -4Ch
.text:00401250 var_C           = dword ptr -0Ch
.text:00401250 var_8           = dword ptr -8
.text:00401250 var_4           = dword ptr -4
.text:00401250
.text:00401250                 push    ebp                     儲存棧低
.text:00401251                 mov     ebp, esp                指向新棧
.text:00401253                 sub     esp, 4Ch                開闢區域性變數空間
.text:00401256                 push    ebx
.text:00401257                 push    esi
.text:00401258                 push    edi                     儲存暫存器環境
.text:00401259                 lea     edi, [ebp+var_4C]       獲得區域性變數空間首地址
.text:0040125C                 mov     ecx, 13h
.text:00401261                 mov     eax, 0CCCCCCCCh
.text:00401266                 rep stosd                       利用rep 加串操作指令 stosd 按照4個位元組.從 eax中取出cc值. 存放到 edi中. 迴圈次數 ecx控制.


.text:00401268                 mov     [ebp+var_4], 8          常量賦值給變數

.text:0040126F                 mov     eax, [ebp+var_4]
.text:00401272                 sub     eax, 0Ah              var_8 = var_4 - 0xA 
.text:00401275                 mov     [ebp+var_8], eax

.text:00401278                 mov     ecx, [ebp+var_4]
.text:0040127B                 sub     ecx, [ebp+var_8]
.text:0040127E                 mov     [ebp+var_C], ecx      var_c = var4 - var_8;

.text:00401281                 mov     edx, [ebp+var_4]
.text:00401284                 add     edx, 5                var_c = var_4 + 5;   上方是 var_4  - -5 ,因為負負得正.所以彙編中使用加法了.
.text:00401287                 mov     [ebp+var_C], edx

.text:0040128A                 xor     eax, eax
.text:0040128C                 pop     edi
.text:0040128D                 pop     esi
.text:0040128E                 pop     ebx
.text:0040128F                 mov     esp, ebp
.text:00401291                 pop     ebp
.text:00401292                 retn
.text:00401292 _main_0         endp

可以根據自己需求,將上面的程式碼進行還原. 當然還原出的高階程式碼可能跟我寫的高階程式碼不一樣.這是正常的.
但是如果還原正確.那麼在IDA中.二進位制十一摸一樣的. 也就是彙編. 此時就算還原正確.

四丶知識總結

總體來講. 如果是常量進行操作.則在編譯期間直接運算完畢了. 如果操作變數則會操作通用暫存器.
使用通用暫存器進行計算.
最重要的一點: 計算機不會做加法.所以 我們的做減法運算的時候. 其實是按照補碼存放的. 使用補碼去操作的.
例如:
11 - 3 我們可以看做 11 + 3(補碼)

可以參考本人編寫的詳細部落格: 部落格連結