簡體   English   中英

簡單的加密匯編程序-訪問沖突寫入內存位置

[英]Simple encryption Assembly Program - Access violation writing to memory location

我必須在該程序中實現一個cdecl調用約定,該約定最初使用的是非標准化約定。 據我所知,它看起來很正確,但是出現了一個未處理的異常錯誤,提示“ Accress違反寫入位置0x00000066,它似乎在程序下降到“ not byte ptr [eax]”行時出現,或者至少在該位置斷開程序后,箭頭指向。

誰能告訴我程序有什么問題以及如何解決? 謝謝。

void encrypt_chars (int length, char EKey)
{   char temp_char;                     

for (int i = 0; i < length; i++)    
{
    temp_char = OChars [i];         
    __asm {
            push   eax
            movzx  eax, temp_char
            push   eax
            lea    eax, EKey
            push   eax
            call   encrypt
            mov    temp_char, al

            pop    eax
    }
    EChars[i] = temp_char;          
return;


// Inputs: register EAX = 32-bit address of Ekey,
//                  ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).

__asm {          

encrypt:

        push ebp
        mov ebp, esp
        mov ecx, 8[ebp] 
        mov eax, 12[ebp]
        push edi                  
        push ecx                  
        not byte ptr[eax]         
        add byte ptr[eax], 0x04   
        movzx edi, byte ptr[eax]  
        pop eax                   
        xor eax, edi              
        pop edi                   
        rol al, 1                 
        rol al, 1                 
        add al, 0x04              
        mov esp, ebp
        pop ebp
        ret                       
}

通過檢查,對加密功能的注釋是錯誤的。 請記住:堆棧向下增長,因此當將參數壓入堆棧時,首先壓入的參數具有較高的地址,因此與堆棧幀中基本指針的偏移量較高。

encrypt的評論說:

// Inputs: register EAX = 32-bit address of Ekey,
//                  ECX = the character to be encrypted

但是,您的呼叫順序為:

movzx  eax, temp_char    ; push the char to encrypt FIRST
push   eax
lea    eax, EKey         ; push the encryption key SECOND
push   eax
call   encrypt

所以角色是推。 所以字符加密,但encrypt被加載它們是這樣的:

; On function entry, the old Instruction Pointer (4 bytes) is pushed onto the stack
; so now the EKey is +4 bytes from the stack pointer
; and the character is +8 bytes from the stack pointer
;

push ebp
mov ebp, esp

; We just pushed another 4 bytes onto the stack (the esp register)
; and THEN we put the stack pointer (esp) into ebp as base pointer
; to the stack frame.
;
; That means EKey is now +8 bytes off of the base pointer
; and the char to encrypt is +12 off of the base pointer
;
mov ecx, 8[ebp]            ; This loads EKey pointer to ECX
mov eax, 12[ebp]           ; This loads char-to-encrypt to EAX

然后代碼繼續嘗試將EAX用作指針(因為它認為這是EKey ),這將導致訪問沖突,因為這是您的字符在首次嘗試將EAX用作指針時進行加密,這是這里:

not byte ptr[eax]

因此,您的調試器指針是正確的! :)

您可以通過交換以下兩個寄存器來修復它:

mov eax, 8[ebp]            ; This loads EKey pointer to EAX
mov ecx, 12[ebp]           ; This loads char-to-encrypt to ECX

最后,完成加密后,您對加密的調用不會清除堆棧指針。 由於您在調用encrypt之前將8個字節的數據壓入了堆棧,並且因為encrypt會執行標准的ret而不會進行堆棧清理,因此您需要在調用之后進行清理:

...
call   encrypt
add    esp, 8
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM