首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >%p在printf中的用法?

%p在printf中的用法?
EN

Stack Overflow用户
提问于 2014-03-20 00:28:23
回答 2查看 1.5K关注 0票数 3

我从这个链接在线阅读了以下代码:05/Lectures/BufferOverflow.html

我对这行中%p的用法感到困惑:

代码语言:javascript
复制
 printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");

它摘自以下代码片段:

代码语言:javascript
复制
 /*
  StackOverrun.c
  This program shows an example of how a stack-based 
  buffer overrun can be used to execute arbitrary code.  Its 
  objective is to find an input string that executes the function bar.
*/

#pragma check_stack(off)

#include <string.h>
#include <stdio.h> 

void foo(const char* input)
{
    char buf[10];

    printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");

    strcpy(buf, input);
    printf("%s\n", buf);

    printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}

void bar(void)
{
    printf("Augh! I've been hacked!\n");
}

int main(int argc, char* argv[])
{
    //Blatant cheating to make life easier on myself
    printf("Address of foo = %p\n", foo);
    printf("Address of bar = %p\n", bar);
    if (argc != 2) 
 {
        printf("Please supply a string as an argument!\n");
        return -1;
    } 
foo(argv[1]);
    return 0;
}

我知道%p是指针的格式化程序,但是为什么格式化程序后面没有值?这里实际打印的值是什么?如果它打印提供给foo函数的参数的地址,那么为什么有5 '%p‘,为什么所有的'%p’不都格式化相同的值?

非常感谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-20 00:30:36

这是利用未定义的行为。

通过故意不向printf提供值,va_arg将从要打印的堆栈中提取任意值。这不是正确的代码。事实上,这段代码片段似乎试图解释黑客技术,这种技术经常利用未定义行为发生时出现的故障。

票数 8
EN

Stack Overflow用户

发布于 2019-06-19 20:04:46

--这段代码很糟糕,对于使用调试器查看堆栈来说,这是一个非常糟糕的替代。不要浪费你的时间,直到/除非你明白它是如何滥用调用约定和它到底是打印的。(并查看编译器生成的代码,查看调用时堆栈指针指向的位置)。

,它依赖于32位x86上典型的堆栈-args调用约定。(因此,变量printf函数将把堆栈上的数据作为额外的args处理)。函数“拥有”它们的arg(并且可以修改它们),但是在实践中,大多数函数不修改它们的堆栈args,而各种函数则更少。

它还依赖于编译器不插入一堆额外的填充,使call printf的ESP由16对齐,这是现代版本的i386系统V所需要的。如果发生这种情况,在您想要用strcpy缓冲区溢出覆盖的真实内容之前会有一些额外的填充指针。

在x86-64代码中,x86-64 System在整数寄存器中传递前6个整数/指针args,因此在格式字符串之后,前5个%p转换将捕获RSI、RDX、RCX、R8和R9中的任何垃圾。(RDI中的格式字符串)。然后,您将从堆栈中获得一些qword,用于其余的%p转换。

在Windows中,调用约定包括“影子空间”:比被调用方拥有的x64高出32个字节,在这里,它们可以转储寄存器args,使args数组与堆栈args相邻。打电话的人必须预订这个空间。strcpy也会出现这种情况,因此可能会有某种程度的平衡,但是仍然要打印RDX、R8和R9中的垃圾。(RCX中的格式字符串)。

通常,大多数用于其他非x86 ISAs的调用约定都有一些寄存器args (通常为4,例如ARM或MIPS),而且大多数不使用阴影空间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22521064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档