假设我已经在堆栈中创建了一个局部变量,或者为字符串分配了内存,现在我想在其中添加一个值。
push ebp
mov ebp, esp
sub esp, 0xff ; 255 bytes
将字符串存储在C:
中的堆栈中strcat(my_str1, "something1");
strcat(my_str1, get_var2());
strcat(my_str1, "something3");
strcat(my_str1, get_var4());
我想在FASM或NASM中没有“strcat”的情况下如何做到这一点:
;1
mov byte ptr [esp - 1], 's'
mov byte ptr [esp - 2], 'o'
mov byte ptr [esp - 3], 'm'
mov byte ptr [esp - 4], 'e'
; and so on
这是怎么做的?关于“get_var2()”和“get_var4()”的部分?
;2
call get_var2
mov ??byte?? ptr [esp - 11], eax
; or lea?
答案 0 :(得分:0)
1)sub esp, 0xff
保持esp
对齐,至少每4个。如果C字符串只需要255个字节(254个字符+零终止符),则分配256个。
2)mov [esp-1],'s'
您已经递减esp
,因此局部变量位于某个[esp+X]
地址(多少取决于您在堆栈上推送的其他值)。或者更确切地使用[ebp-Y]
和类似C的函数序言,首先在ebp
初始化堆栈帧指针(push ebp
mov ebp,esp
sub esp,local_vars_size
然后结束{{1} } mov esp,ebp
pop ebp
)。
但永远不要触及ret
下的值,除非你确切知道自己在做什么以及为什么(比如写入64b模式的红色区域),因为如果你不确定,那么在99%它会以错误,通常是难以找到的错误之一,这很少影响代码。
esp
完成(顺便说一下,你可能确实想设置mov [esp-4],dword 'emos'
?)
是的,这是编译器在本地分配的堆栈空间中设置较短常量的常用方法,对于较大的数据,它们可以使用来自常量模板数据的'some'
。
4)关于memcpy
,所以get_var2()
会返回稳定的get_var2()
指针吗?然后你将不得不重新实现完整(char *)
,除非你可以知道字符串中已经有多少个字符,以及将添加多少个字符。如果strcat
返回某个值,则首先将其转换为某些字符并确定其数量等等。然后您可以直接编写它们,或者在某个循环中等等。太宽泛了。
同样在本地堆栈上运行时,我会在变量周围分配一些安全空间,以防超出边界并覆盖几个字节。您甚至可以先将这些额外的字节设置为某个canary值,然后在函数结束时检查它,看看是否发生了一些堆栈覆盖(至少在调试版本中)。而不是get_var2()
您需要strcat
或类似,以避免恶意数据堆栈溢出。
否则,正如Jester建议的那样,可能首先尝试在固定内存缓冲区上实现strncat
,这样您就可以专注于代码本身,而不是解析本地内存的分配。然后你可以在它上面构建,甚至将它用作函数调用。