【问题标题】:Difference between printing value at address in C and in GDBC和GDB中地址打印值之间的差异
【发布时间】:2020-09-29 16:32:42
【问题描述】:

我一直在尝试从程序中的 main 获取返回地址。这里是:

#include <stdio.h>

int main(int argc, char **argv)
{
        char buffer[64];
        printf("[%p]: ", buffer+64+8+4);
        printf("%p ", *(buffer+64+8+4));
        printf("%p ", *(buffer+64+8+5));
        printf("%p ", *(buffer+64+8+6));
        printf("%p \n", *(buffer+64+8+7));
}

我添加了 64 来覆盖缓冲区,8 用于填充(通过 gdb 计算),最后 4 用于在堆栈上推送的 ebp。堆栈中的下一件事应该是 main 的返回地址。
运行程序产生:
[0xbffff7dc]: 0x76 0xffffffdc 0xffffffea 0xffffffb7

但是从 gdb,我得到了

(gdb) x/x 0xbffff7dc
0xbffff7dc:     0xb7eadc76

我可以看到,在程序的STDOUT中,返回地址有意义的部分位于LSB,所有高字节都是0xff(除了0x76,不知道为什么)。

【问题讨论】:

  • ff 填充您的值的原因是在您的系统上char 是一个有符号值,并且在打印之前它首先扩展为int 的大小。对于负值,这包括“符号扩展”。由于0x76 不是负数,所以没有符号位被复制到高位。

标签: c gdb reverse-engineering


【解决方案1】:

我很快意识到在 C 中取消引用指针完全取决于指针的类型。
任何*(buffer+XXX) 类型的表达式都只会返回位于地址的单字节数据,因为bufferchar*(而char 是1 个字节)。

解决方案是将地址转换为int*(或任何能够保存地址的数据类型,例如char**取消引用之前。

最后,我想出了这个:

#include <stdio.h>

int main(int argc, char **argv)
{
        char buffer[64];
        //gets(buffer);
        printf("[%p]: ", buffer+64+8+4);
        printf("%p \n", *( (char**) (buffer+64+8+4)));
}

成功输出 [0xbffff7dc]: 0xb7eadc76

【讨论】:

    猜你喜欢
    • 2017-10-13
    • 1970-01-01
    • 2021-03-12
    • 2012-04-21
    • 2010-12-21
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多