动态地将字符串加载到局部变量中

时间:2017-02-21 17:37:56

标签: assembly nasm fasm

假设我已经在堆栈中创建了一个局部变量,或者为字符串分配了内存,现在我想在其中添加一个值。

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?

1 个答案:

答案 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%它会以错误,通常是难以找到的错误之一,这很少影响代码。

<3>在NASM中,这4个mov可以使用单个dword常量esp完成(顺便说一下,你可能确实想设置mov [esp-4],dword 'emos'?)

是的,这是编译器在本地分配的堆栈空间中设置较短常量的常用方法,对于较大的数据,它们可以使用来自常量模板数据的'some'

4)关于memcpy,所以get_var2()会返回稳定的get_var2()指针吗?然后你将不得不重新实现完整(char *),除非你可以知道字符串中已经有多少个字符,以及将添加多少个字符。如果strcat返回某个值,则首先将其转换为某些字符并确定其数量等等。然后您可以直接编写它们,或者在某个循环中等等。太宽泛了。

同样在本地堆栈上运行时,我会在变量周围分配一些安全空间,以防超出边界并覆盖几个字节。您甚至可以先将这些额外的字节设置为某个canary值,然后在函数结束时检查它,看看是否发生了一些堆栈覆盖(至少在调试版本中)。而不是get_var2()您需要strcat或类似,以避免恶意数据堆栈溢出。

否则,正如Jester建议的那样,可能首先尝试在固定内存缓冲区上实现strncat,这样您就可以专注于代码本身,而不是解析本地内存的分配。然后你可以在它上面构建,甚至将它用作函数调用。