2017-02-21 56 views
0

假设我创建了一个本地变量或者为字符串分配内存,现在我想在其中添加一个值。将字符串动态加载到本地变量

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()); 

我想undertand怎么做,没有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? 
+3

尝试在C中首先实现'strcat'(不使用任何库函数)。然后你会看到它是如何工作的,并且你可以在asm中做同样的事情。 – Jester

回答

0

1)sub esp, 0xff保持esp排列,每4至少如果你需要C字符串只有255个字节(254个字符+ 0终结),然后分配256

2)mov [esp-1],'s'你已经递减esp,所以本地变量是在一些[esp+X]地址(多少取决于你有多少其他值你推堆栈)。或者宁愿使用[ebp-Y]与C类功能序幕,初始化ebp第一个(push ebpmov ebp,espsub esp,local_vars_size ..然后结尾mov esp,ebppop ebpret)初始化堆栈帧指针。除非你确切地知道你在做什么以及为什么(例如在64b模式下写入红色区域),因为如果你不确定,那么在99%的情况下它会以错误结束,并且通常很难找到,这很少影响代码。

3)在NASM的4个MOVS是可以做到单DWORD不变mov [esp-4],dword 'emos'(顺便说一句,你可能没有要设置'some'?)

是的,这就是常见的方式编译器如何设置更短的常量在本地分配的堆栈空间,对于更大的数据,它们可以使用来自恒定模板数据的memcpy

4)约get_var2(),所以get_var2()返回稳定(char *)指针?那么你将不得不重新实现完整的strcat,除非你可以告诉字符串中已经有多少个字符,并且将添加多少个字符。如果get_var2()返回一些值,你首先将它转换为一些字符,并决定多少,等等。然后你可以直接写它们,或者在某些循环等等。太宽泛。

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

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

+0

'1)sub esp,0xff保持esp对齐,至少每4。 - 为什么4? – Kevin

+0

@Kevin:在x86上,即使没有对齐的内存访问权限,也会大部分消失(但支付相当大的性能损失)。但是对于某些SIMD(和FP?)指令,您将在非法内存访问(通常需要16B对齐,通常在64b调用约定中强制执行,但不在32b中)中崩溃。仅仅由于性能的原因,它被认为是不够的做法永远不会做到这一点。它甚至没有任何好处,除了保留1-3字节,这在x86世界中并不相关(甚至数据结构只是为了使其成员对齐而被填充,浪费了比这更多的字节)。 – Ped7g

相关问题