【问题标题】:I keep getting a segmentation fault in my c code when I make it a exe当我将其设置为 exe 时,我的 c 代码中不断出现分段错误
【发布时间】:2012-01-03 14:47:13
【问题描述】:

我正在尝试学习 shell 代码,但我的 Ubuntu 机器中不断出现分段错误。

/*shellcodetest.c*/ 
char code[]="\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01"\
        "\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8"\
        "\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f\xe8\xd8\xff\xff\xff"\
        "\x68\x65\x6c\x6c\x6f\xe8\xce\xff\xff\xff\x68\x65\x6c\x6c"\
        "\x6f\xe8\xc4\xff\xff\xff\x68\x65\x6c\x6c\x6f\xe8\xba\xff"\
        "\xff\xff\x68\x65\x6c\x6c\x6f";
int main(int argc, char **argv)
{
    int (*func)();
    func = (int (*)()) code;
    (int)(*func)();
}

我不明白为什么这会失败。我在想也许是一个空指针。 如果您有任何想法我可以跟进,那就太好了。

【问题讨论】:

  • 它有什么作用?我的意思是,你能展示一个反汇编或任何东西吗?
  • 你应该问的问题是,为什么以及如何工作。
  • 你确定你的shellcode是正确的吗?
  • 疯狂猜测:地址空间随机化?
  • 确保代码的架构正确。如果这是 32 位代码,而您正在编译 64 位二进制文​​件,那么它可能无法正常工作。

标签: c segmentation-fault


【解决方案1】:

好的,现在让我们检查您的代码。

char code[]="\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01"\

上面的行创建了一个名为code 的全局字符数组,并且已经用一堆十六进制进行了初始化。 char[] 的内存将在data-segment 中分配。

int (*func)();

上面的行声明了一个pointer-to-a-function,它不接受任何参数并返回int。用于此的内存将在stack 中分配,但此变量应指向存储code 的内存位置

func = (int (*)()) code;

以上行将code (global-character-array) 转换为func (pointer-to-a-function) 指向它!此操作是未定义的行为,因为假设指向 code-segmentstack 变量现在指向 data-segment

即使分配成功(可能是因为奇迹),那么在下一行中取消引用它们绝对不会起作用!

更多关于变量在heapstackcode段中如何分配的信息,请参考this

【讨论】:

  • 实际上shellcode会分配在栈上,而不是数据段中,分配应该总是有效的,因为它只是分配指针
  • 但是,堆栈可能无法执行。该数组是全局的,但很可能不会在堆栈上分配。
【解决方案2】:

这个程序会调用大量未定义的行为,因此,按照标准,任何事情都可能发生。对于这样的程序来说,分段错误是完全可以接受的结果。

【讨论】:

  • 我认为“可接受的结果”是错误的词,因为他在问如何解决它。也许是“预期的结果”
【解决方案3】:

你可以直接定义:

 int (*func)() = (int (*)()) "\xeb\x19\x31\xc0..."

它会起作用的。

但它仍然是未定义的行为。

【讨论】:

    【解决方案4】:

    不是答案,但可能会有所帮助。我在 64 位 Ubuntu 上拆解它。在 32 位上会有所不同。

    (gdb) disassemble /mr func,0x60108A
    Dump of assembler code from 0x601040 to 0x60108a:
    0x0000000000601040 <code+0>:     eb 19  jmp    0x60105b <code+27>
    0x0000000000601042 <code+2>:     31 c0  xor    %eax,%eax
    0x0000000000601044 <code+4>:     31 db  xor    %ebx,%ebx
    0x0000000000601046 <code+6>:     31 d2  xor    %edx,%edx
    0x0000000000601048 <code+8>:     31 c9  xor    %ecx,%ecx
    0x000000000060104a <code+10>:    b0 04  mov    $0x4,%al
    0x000000000060104c <code+12>:    b3 01  mov    $0x1,%bl
    0x000000000060104e <code+14>:    59 pop    %rcx
    0x000000000060104f <code+15>:    b2 05  mov    $0x5,%dl
    0x0000000000601051 <code+17>:    cd 80  int    $0x80
    0x0000000000601053 <code+19>:    31 c0  xor    %eax,%eax
    0x0000000000601055 <code+21>:    b0 01  mov    $0x1,%al
    0x0000000000601057 <code+23>:    31 db  xor    %ebx,%ebx
    0x0000000000601059 <code+25>:    cd 80  int    $0x80
    0x000000000060105b <code+27>:    e8 e2 ff ff ff callq  0x601042 <code+2>
    0x0000000000601060 <code+32>:    68 65 6c 6c 6f pushq  $0x6f6c6c65
    0x0000000000601065 <code+37>:    e8 d8 ff ff ff callq  0x601042 <code+2>
    0x000000000060106a <code+42>:    68 65 6c 6c 6f pushq  $0x6f6c6c65
    0x000000000060106f <code+47>:    e8 ce ff ff ff callq  0x601042 <code+2>
    0x0000000000601074 <code+52>:    68 65 6c 6c 6f pushq  $0x6f6c6c65
    0x0000000000601079 <code+57>:    e8 c4 ff ff ff callq  0x601042 <code+2>
    0x000000000060107e <code+62>:    68 65 6c 6c 6f pushq  $0x6f6c6c65
    0x0000000000601083 <code+67>:    e8 ba ff ff ff callq  0x601042 <code+2>
    0x0000000000601088 <code+72>:    68 65 6c 6c 6f pushq  $0x6f6c6c65
    

    在第一行显示 SIGSEGV 失败:

    (gdb) display /3i $pc
    1: x/3i $pc
    => 0x601040 <code>: jmp    0x60105b <code+27>
    0x601042 <code+2>:  xor    %eax,%eax
    0x601044 <code+4>:  xor    %ebx,%ebx
    

    会不会因为跳转到数据段而失败?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多