2012-11-10 60 views
0

我有这个shell代码的问题。 当我运行汇编代码时,它会打印caracter,但是当我将它作为c函数调用时,它不会。 我用gdb来测试所有执行的指令,它似乎执行所有的指令。 这是非常奇怪的,因为我调试了asm和c版本,他们也是这样做的,但是在int 0x80中它并没有为C代码打印任何东西。 这是C代码:外壳代码打印字符(64位)

#include <stdio.h> 
#include <sys/mman.h> 
#include <string.h> 
#include <stdlib.h> 

int (*sc)(); 
/**************************************************************** 
    0000000000000000 <main>:         /
     0: 48 31 c9    xor %rcx,%rcx   /
     3: 48 31 c0    xor %rax,%rax   /
     6: eb 13     jmp 1b <n>    /
                   /
    0000000000000008 <et>:          /
     8: 59      pop %rcx     /
     9: 48 31 c0    xor %rax,%rax   /
     c: 48 31 db    xor %rbx,%rbx   /
     f: 48 31 d2    xor %rdx,%rdx   /
     12: b0 04     mov $0x4,%al    /
     14: b3 01     mov $0x1,%bl    /
     16: b2 01     mov $0x1,%dl    /
     18: cd 80     int $0x80    /
     1a: c3      retq      /
                   /
    000000000000001b <n>:          /
     1b: e8 e8 ff ff ff   callq 8 <et>    /
                   /
    0000000000000020 <abc>:          /
     20: 77      .byte 0x77     /
     ...              /
******************************************************************/ 



char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw"; 

int main(int argc, char **argv) { 

    char *ptr = mmap(0, sizeof(shellcode), 
      PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON 
      | MAP_PRIVATE, -1, 0); 

    if (ptr == MAP_FAILED) { 
     perror("mmap"); 
     exit(-1); 
    } 

    memcpy(ptr, shellcode, sizeof(shellcode)); 
    sc = ptr; 

    (void)((void(*)())ptr)(); 
    printf("\n"); 

    return 0; 
} 

这是NASM代码:

global main 

main:       ; main 

xor rcx, rcx   ; eficient way turning register to 0 
xor rax, rax   ; exclusive or 

jmp n    
et: 
pop rcx 

xor rax, rax 
xor rbx, rbx 
xor rdx, rdx 
mov al, 4      ; Number of system call (write) 
mov bl, 1      ; argument(1=stdout) 
mov dl, 1      ; number of characters 
int 0x80 

ret 

n: 
call et 
abc: db 'w'    

编辑: 我已经解决了这个问题。 在这个网页:http://www.exploit-db.com/papers/13065/我发现在64位系统调用必须使用int 0x80系统调用insted调用,并且参数的寄存器是不同的。 然后我发现这个其他网页:http://cs.lmu.edu/~ray/notes/linuxsyscalls/。它有一些关于做这些系统调用的例子,认为这是一个很好的网页。

但现在的问题是,为什么它与纳斯姆代码一起工作?它是否兼容?可能是汇编程序代码在兼容模式下运行,因为汇编程序检测到int 0x80指令,而在C语言中编译器不能,因为它无法解释shellcode?

我离开这里工作的C代码:

#include <stdio.h> 
#include <sys/mman.h> 
#include <string.h> 
#include <stdlib.h> 

int (*sc)(); 
/**************************************************************** 
    0000000000000000 <main>:         /
     0: 48 31 c9    xor %rcx,%rcx   /
     3: 48 31 c0    xor %rax,%rax   /
     6: eb 16     jmp 1e <n>    /
                   /
    0000000000000008 <et>:         /
     8: 5e      pop %rsi    /
     9: 48 31 c0    xor %rax,%rax   /
     c: 48 31 db    xor %rbx,%rbx   /
     f: 48 31 d2    xor %rdx,%rdx   /
     12: b0 01     mov $0x1,%al   /
     14: b3 01     mov $0x1,%bl   /
     16: 48 89 df    mov %rbx,%rdi   /
     19: b2 01     mov $0x1,%dl   /
     1b: 0f 05     syscall     /
     1d: c3      retq      /
                   /
    000000000000001e <n>:          /
     1e: e8 e5 ff ff ff   callq 8 <et>    /
                   /
    0000000000000023 <abc>:         /
     23: 77      .byte 0x77    /
                   /
****************************************************************/ 


char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x16\x5e\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x01\xb3\x01\x48\x89\xdf\xb2\x01\x0f\x05\xc3\xe8\xe5\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw"; 

int main(int argc, char **argv) { 

    char *ptr = mmap(0, sizeof(shellcode), 
      PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON 
      | MAP_PRIVATE, -1, 0); 

    if (ptr == MAP_FAILED) { 
     perror("mmap"); 
     exit(-1); 
    } 

    memcpy(ptr, shellcode, sizeof(shellcode)); 
    sc = ptr; 

    (void)((void(*)())ptr)(); 
    printf("\n"); 

    return 0; 
} 

回答

1

你可能正在构建的ELF文件作为32位之一。即使您的操作系统是64位,如果二进制文件是32位,它也会以兼容模式运行。

同样的事情发生在Windows上(它被称为“Windows-on-Windows-64”或“WOW64”)。

+1

可能你是对的,我会稍后尝试编译它,并告诉你exec是否为32位。感谢你的回答。 (我正在使用Linux btw) – user1754322

+0

这是肯定的。 64位机器上的写入系统调用是数字1,它必须保存在rax寄存器中,并由syscall指令调用(no int 0x80)。他将64位寄存器与32位指令混合在一起。 – sinkmanu