Assembly Strncat已复制到具有偏移量的目标

Assembly Strncat已复制到具有偏移量的目标,assembly,reverse-engineering,exploit,Assembly,Reverse Engineering,Exploit,所以我想在strncat上分解这个简单的c程序 #include <string.h> int main(int argc, char **argv) { char buf[128]; strncat(buf,argv[1],sizeof(buf)); } #包括 intmain(intargc,字符**argv){ char-buf[128]; strncat(buf,argv[1],sizeof(buf)); } 拆开后 所以问题是a

所以我想在strncat上分解这个简单的c程序

 #include <string.h>

 int main(int argc, char **argv) {  
    char buf[128];
    strncat(buf,argv[1],sizeof(buf));    
   }
#包括
intmain(intargc,字符**argv){
char-buf[128];
strncat(buf,argv[1],sizeof(buf));
}
拆开后

所以问题是argv中的字符串要复制到[rbp-0x80] rsi有一个指向argv的指针,rdi为[rbp-0x80]

在我的例子中,[rbp-0x80]是0x7FFFFFE0D0

这是我作为argv
perl-e'print“B”x10传递的输入;打印“A”x118'

所以0x7FFFFFE0D0-0x7fffffffe0da应该有4242。。。 但是有一个地址存储在0x7FFFFFE0D5-0x7FFFFFE0D0中

这是调用strncat函数之前的屏幕截图

以下是调用strncat函数后的屏幕截图

我不明白为什么字符串从0x7FFFFFE0D6开始,而不是从0x7FFFFFE0D0开始

有什么想法吗

编辑:

输入屏幕截图

您没有初始化
buf[]
,其中未初始化的垃圾恰好不是以
0
开头。您使用的是
strncat
,而不是
strncpy
,因此它查找现有字符串的开头。幸运的是,缓冲区的开头附近有一个零,因此实际上不会使其溢出。(这是可能的,因为您使用了
strncat
错误)

令人惊讶的是,gcc和clang对strncat的了解都不足以警告读取未初始化的数据:


(不同于strncpy)。而且计数也不包括strlen(dst)计数是它从源读取的最大字符数,而不是dest缓冲区的大小。

@PeterCordes这就是我的想法,所以我使用printf打印输入字符串hello,我得到hello作为输出,如果我有'perl-e'print“A”x15,我得到15a,但在16之后得到�����aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?我会用屏幕截图更新这个问题。所以你实际上是用
aaaaaaaaaaaa…
作为参数,而不是
perl-e'print…
?i、 您使用的是perl命令的输出,而不是像您的问题所说的perl命令的文本?反引号是
code
的堆栈溢出标记。您应该说您正在使用
$(perl-e…
作为参数。但是无论如何,
buf
开头附近的非ascii垃圾正是您的gdb转储所显示的。为什么这些都令人惊讶?如果以字节大小的块而不是字(因为x86是小尾端)转储,则更容易阅读。每个32位十六进制值的最后一个(最低有效)字节是内存顺序中的第一个字节。@PeterCordes perl-e“print”A“x10”产生10 A,只是为了简单:)只是想知道为什么字符串Hello(输入小于16字节)的输出没有垃圾egcc会发出保持堆栈16B对齐的代码。可能更长的arg字符串会占用堆栈上更多的空间,这就是
rsp
main
中下降16B的阈值。所以
buf[]
有不同的未初始化垃圾。是的,这就是问题所在:D,当调用strncat之前,0x7fffffffe0d0有7fffffffffe250,以空字符结尾,所以它被附加到它后面。现在的问题是在正常运行时,即/a.out hello,我在使用gdb运行时得到hello,我得到垃圾值o.o