Изменение адреса в шеллкоде во время выполнения - PullRequest
2 голосов
/ 14 июля 2020

Моя цель - создать шелл-код, который вызывает WinExec и запускает notepad.exe. Самый простой код (хотя на самом деле окружен какой-то другой сборкой gcc):

push 0x00646170
push 0x65746F6E 

push 5

lea eax, [esp + 0x4]
push eax

call 0x76E137C0
add esp, 32

Он помещает в стек «блокнот \ 0», затем 5, затем адрес "notepad" строка, затем, наконец, вызывает 0x76E137C0. 0x76E137C0 - это адрес WinExec, по-видимому, находящийся по адресу, когда ASLR отключен на моей машине (32-битная Windows 10 ВМ).

Я беру этот код, собирая его, используя gcc (просто gcc shell.c -o shell.exe), а затем objdump. Как только я нахожу инструкции, я беру байты, которые они показывают:

40141e:       68 70 61 64 00          push   $0x646170
401423:       68 6e 6f 74 65          push   $0x65746f6e
401428:       6a 05                   push   $0x5
40142a:       8d 44 24 04             lea    0x4(%esp),%eax
40142e:       50                      push   %eax
40142f:       e8 8c 23 a1 76          call   76e137c0 <.debug_str+0x76a027c0>
401434:       83 c4 20                add    $0x20,%esp

Затем я превращаю это в строку байтов и пытаюсь выполнить:

#include <windows.h>
#include <winbase.h>

int main() {

    char* shellcode =
       "\x68\x70\x61\x64\x00\x68\x6e\x6f\x74\x65\x6a\x05\x8d\x44\x24\x04\x50\xe8\xbc\x37\xe1\x76\x83\xc4\x20";

    ((void(*)())shellcode)();

    return 0;
}

Проблема в том, что если я затем скомпилирую вышеуказанную простую программу C и запустил ее, ничего не произойдет. Если я открою его в Immunity и step, я вижу, что инструкции были сохранены, за исключением для адреса:

Снимок экрана отладчика иммунитета

Адрес находится в неправильном модуле и, похоже, частично выполняет функцию. Если я уйду и попаду в call, я получу нарушение доступа. Однако, если я перезапускаю и в Immunity заменяю call 77218816 на call 0x76E137C0, затем продолжаю, он работает нормально, и появляется блокнот.

Я не могу сказать, почему адрес меняется, хотя пока больше ничего нет. Кто-нибудь видит, что я делаю не в порядке?

Вся начальная сборка

    .file   "shell.c"
    .intel_syntax noprefix
    .text
    .def    ___main;    .scl    2;  .type   32; .endef
    .section .rdata,"dr"
    .align 4
LC0:
    .ascii "notepad\0"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    lea ecx, [esp+4]

    and esp, -16
    push    DWORD PTR [ecx-4]
    push    ebp

    mov ebp, esp
    push    ecx

    push 0x00646170
    push 0x65746F6E 
    
    push 5
    
    lea eax, [esp + 0x4]
    push eax
    
    call 0x76E137C0
    add esp, 32
    
    sub esp, 8
    mov eax, 0
    mov ecx, DWORD PTR [ebp-4]

    leave

    lea esp, [ecx-4]

    ret

1 Ответ

3 голосов
/ 15 июля 2020

Использование call как это относится к EIP. Вы не запускаете свой шелл-код по тому же адресу, для которого вы его скомпилировали, поэтому он не может call выйти из себя таким образом. Для быстрого и грязного обходного пути вы можете выполнить mov eax, 0x76E137C0, а затем call eax, что является абсолютным.

...