【问题标题】:Overflowed bytes different than those I see on GDB?溢出的字节与我在 GDB 上看到的不同?
【发布时间】:2020-03-12 19:17:29
【问题描述】:

我正在尝试执行ProtoStar stack5 challenge。我知道解决方案(在写完之后),但我正在尝试提出不同的方法。

这是我们试图在其上执行 shellcode 的程序的源代码:

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

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

所以只是为了查看寄存器中发生了什么,我执行以下操作:

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7b0:     0x41414141      0xbffff800      0xbffff85c      0xb7fe1848
0xbffff7c0:     0xbffff810      0xffffffff
(gdb) p $ebp
$1 = (void *) 0xbffff7a8
(gdb)

很好,我用 41414141 溢出了返回地址。正如预期的那样。现在,我要做的是将返回地址更改为接下来的 4 个字节,这样

00xbffff7a8: |saved frame pointer| - | return address| - |shellcode part 1| - |...| - |shellcode part n|

但是,当我尝试写 76 个“41”,然后是地址 0xbffff7a8 + 4(即 0xbffff7b0)时,它一直在写错误的东西。这是我输入的内容:

41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141b0f7ffbf

请注意,我们使用的是小端系统。

但是,当我输入这个(作为 ASCII)时,这就是我在 $esp 和 $ebp 上看到的:

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA°÷ÿ¿
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff760:     0xbffff770      0xb7ec6165      0xbffff778      0xb7eada75
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0xb7c3b0c2
0xbffff7b0:     0xbfc2bfc3      0xbffff800      0xbffff86c      0xb7fe1848
0xbffff7c0:     0xbffff820      0xffffffff ...
(gdb) p $ebp
$1 = (void *) 0xbffff7a8

如您所见,写入的是 0xb7c3b0c2 而不是预期的 0xbffff7b0

有人知道这是为什么吗?

注意:我意识到我真正想要的地址是 0xbffff7ac,而不是 0xbffff7b0。我会解决这个问题,但它不会改变我遇到的问题。

【问题讨论】:

  • @ChristianGibbons 使用gets() 的目的是导致溢出。常见的示例代码暴露了在没有边界检查的情况下接受输入的缺陷(以及该 SO 帖子中提到的所有其他内容)。 gets() 的“坏”用法是故意的。
  • @VeridianDynamics 我知道这一点。我正在尝试使用溢出,但我在堆栈上找到的字节与我输入的字节不同(请参阅问题的最后一部分)。
  • 呃,哈哈,我回复了其他建议你不要使用 gets() 的人。他们显然删除了他们的评论。你能告诉我你是如何输入字节的吗?
  • @VeridianDynamics 没问题 :) 要获得 $ebp + 0x4,我需要 76 个字符。所以我输入了 'A' 76 次,然后我输入了相当于 b0 f7 ff bf 的 asccii。当我查看 GDB 上的堆栈时,一切都是我所期望的值,除了 b0 f7 ff bf 部分。如您所见,改为写入 0xb7c3b0c2。如果您需要更多信息,问题的结尾会更清楚。感谢您的回复!
  • 您输入了哪些准确的 ASCII 码?

标签: c security debugging gdb buffer-overflow


【解决方案1】:

所以我最终在LiveOverflow's subreddit 上发布了这个问题,LiveOverflow 将我指向了this video 的方向。

视频会比我解释得更好,但本质上,python2 和 python3 不会将十六进制打印到 ascii 中。 Python3 插入额外的字符,而 python2 打印原始的十六进制字符串。

我强烈建议您观看视频,因为它有深入的解释。

This@dsh 回答的另一个问题的答案也解释了它:

字节序列 C3 BE 是 UTF-8 编码的表示 字符 U+00FE。

Python 2 将字符串处理为字节序列,而不是 人物。所以 '\xfe' 是一个包含一个字节的 str 对象。

在 Python 3 中,字符串是 (Unicode) 字符的序列。所以 代码 '\xfe' 是一个包含一个字符的字符串。当您打印 字符串,它必须被编码为字节。由于您的环境选择了 UTF-8 的默认编码,相应地进行了编码。

如何解决这个问题取决于您的数据。是字节还是字符?如果 字节,然后更改代码以告诉解释器:print(b'\xfe')。 如果是字符,但您想要不同的编码,然后编码 相应的字符串: print( '\xfe'.encode('latin1') ).

【讨论】:

    猜你喜欢
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多