错误:对helloworld的shellcode(at& t)的非法指令。

时间:2014-02-05 02:35:01

标签: c shellcode

我正在努力学习如何撰写shellcode。在四处搜寻之后,我为自己的世界编写了自己的shellcode。我认为逻辑是正确的,但不知何故,当我用shellcode编译包装器时,它总是给我“非法指令”。

有人可以帮我查一下这段代码的错误:

的Shellcode

    .section .data
    .section .text

    .globl _start

        jmp dummy 

     _start:
            # write(1, message, 13)
            mov     $4, %al                # system call 4 is write
            mov     $1, %bl                # file handle 1 is stdout
            popl    %ecx
            mov     $12, %dl               # number of bytes to write
            int     $0x80                   # invoke operating system code

            # exit(0)
            xor     %eax, %eax
            mov     $1, %al                # system call 1 is exit
            xor     %ebx, %ebx              # we want return code 0
            int     $0x80                   # invoke operating system code

    dummy:
        call _start
        .string  "Hello, World"

运行objdump后:

    file format elf32-i386


    Disassembly of section .text:

    00000000 <_start-0x2>:
       0:   eb 11                   jmp    13 <dummy>

    00000002 <_start>:
       2:   b0 04                   mov    $0x4,%al
       4:   b3 01                   mov    $0x1,%bl
       6:   59                      pop    %ecx
       7:   b2 0c                   mov    $0xc,%dl
       9:   cd 80                   int    $0x80
       b:   31 c0                   xor    %eax,%eax
       d:   b0 01                   mov    $0x1,%al
       f:   31 db                   xor    %ebx,%ebx
      11:   cd 80                   int    $0x80

    00000013 <dummy>:
      13:   e8 fc ff ff ff          call   14 <dummy+0x1>
      18:   48                      dec    %eax
      19:   65                      gs
      1a:   6c                      insb   (%dx),%es:(%edi)
      1b:   6c                      insb   (%dx),%es:(%edi)
      1c:   6f                      outsl  %ds:(%esi),(%dx)
      1d:   2c 20                   sub    $0x20,%al
      1f:   57                      push   %edi
      20:   6f                      outsl  %ds:(%esi),(%dx)
      21:   72 6c                   jb     8f <dummy+0x7c>
      23:   64                      fs
        ...

我使用的C Wrapper

    char code[] = "\xeb\x11"
                    "\xb0\x04"
                    "\xb3\x01"
                    "\x59"
                    "\xb2\x0c"
                    "\xcd\x80"
                    "\x31\xc0"
                    "\xb0\x01"
                    "\x31\xdb"
                    "\xcd\x80"
                    "\xe8\xfc\xff\xff\xff"
                    "\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64";



    void main() {
            int (*func)();
            func = (int(*)()) code;
            (int) (*func)();
    }

1 个答案:

答案 0 :(得分:1)

您的代码存在一些问题。

首先,您只需设置所有参数寄存器的低字节(即albldl)。您需要设置完整的32位。当你执行现在的方式时,剩下的24位中剩下的任何东西都会被传递给内核。

此外,在您的C代码中,call不正确:

"\xe8\xfc\xff\xff\xff"

这实际上是call $+1,这是调用指令的第二个字节,这就是你获取非法指令的原因。

我不确定你是如何到达code变量中的字节的,但是你需要重新组装。


使用gcc -m32在Fedora 17上使用gcc 4.7.2进行测试。 (对不起,我只使用英特尔语法)

char code[] __attribute__((section(".text"))) = 
    "\xeb\x17"                   // jmp $+19 
    "\xB8\x04\x00\x00\x00"       // mov eax, 4   ; (sys_write)
    "\x31\xDB"                   // xor ebx, ebx
    "\x43"                       // inc ebx
    "\x59"                       // pop ecx      ; (addr of string pushed by call below)
    "\x31\xD2"                   // xor edx, edx
    "\xb2\x0c"                   // mov dl, 0Ch  ; (length of string)
    "\xcd\x80"                   // int 80h

    "\x31\xc0"                   // xor eax, eax
    "\xb0\x01"                   // mov al, 1    ; (sys_exit)
    "\x31\xdb"                   // xor ebx, ebx
    "\xcd\x80"                   // int 80h
    "\xe8\xe4\xff\xff\xff"       // call $-23
    "\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x00";  // "Hello, World"

void main() {
    int (*func)();
    func = (int(*)()) code;
    (int) (*func)();
}

请注意,有一些方法可以使代码更小,但这当然是留给读者的练习。


如果您要使用这样的手动调整组件,请准备好调试,调试和调试。 Learn how to use GDB现在,或者你将永远无助。在程序集的开头设置断点(b code)并逐步执行它。你很快就会发现出了什么问题。