(程序集8086)如何从函数返回到不同的段?

时间:2015-06-05 10:16:13

标签: assembly stack stack-overflow x86-16

我得到了一份写入节目的作品。一个从用户那里获得输入,使用一个在堆栈上分配字符串的函数,并一次写入一个字符,直到它得到一个" Enter"。另一个程序使用第一个的缺陷,并通过堆栈overflaw,更改函数的返回地址,并将其指向恶意代码(我写入堆栈)。

我的问题是函数没有返回到我放入堆栈的地址(在StackSegment中),而只是转到CodeSegment中的地址。 这是获取输入的函数:( printStr函数从堆栈打印)

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

1 个答案:

答案 0 :(得分:0)

如果不允许修改代码,则在代码段中的任何位置搜索0CBh或0CAh字节。这些是远程返回指令,但实际上它们并没有被代码用于此目的。您只需要找到具有这些值之一的字节。更改函数的近返回地址(堆栈上的单个16位值),使其返回到该字节,然后在堆栈上放置恶意代码的偏移量和段。

请注意,0CAh字节是远返回的RET imm16 形式,这会导致它从堆栈中弹出参数。如果您使用此字节,您可能需要重新调整堆栈。

如果找不到0CBh / 0CAh字节,那么如果您知道堆栈段距离代码段不太远,那么您还有另一个选项。您可以使用堆栈上的代码相对于代码段的偏移作为近返回地址。因此,如果堆栈段位于3182h,则代码段位于3040h(随机选择一个数字),并且您的代码位于堆栈段中的偏移64h处,然后您的代码位于代码中的偏移(3182h - 3040h) * 16 + 64h = 1484h处分割。在这种情况下,您将使用1484h而不是3182h:0066h替换返回地址。

如果您没有这些选项可供您使用,那么我无法想到任何其他明显的解决方案。其他标准的堆栈粉碎技术可能不适用。也许return oriented programming,但你的目标可执行文件中可能没有标准库,可能没有很多代码可以借用chucks。 (虽然后者意味着堆栈段应远离代码段。)