• B правой части каждого сообщения есть стрелки и . Не стесняйтесь оценивать ответы. Чтобы автору вопроса закрыть свой тикет, надо выбрать лучший ответ. Просто нажмите значок в правой части сообщения.

Не возвращается управление после исполнения шеллкода

07.08.2020
10
2
BIT
0
Написал шеллкод, пишу инжектор на С++. Получаю PID процесса, открываю его, использую VirtualAlloc для выделения памяти под шеллкод. Записываю шеллкод в выделенную память через WriteProcessMemory, получаю адресс, куда был записан шеллкод. Открываю дебаггер, перехожу по адрессу, ставлю бряк, в инжекторе перед исполнением стоит getchar(), я тыкаю any key и в дебаггере вызывается бряк, но проблема в том, что в конце, после того как была найдена функция, в моём случае - MessageBoxA, и она была вызвана - то управление никуда не возвращается. Код выглядит следующим образом:

Код:
xor ecx, ecx                                                           
mov eax, fs:[ecx + 0x30]                                   
mov eax, [eax + 0xc]                             
mov esi, [eax + 0x14]                   
lodsd                                         
xchg eax, esi                                 
lodsd                                       
mov ebx, [eax + 0x10]                             
mov edx, [ebx + 0x3c]                         
add edx, ebx                                       
mov edx, [edx + 0x78]                   
add edx, ebx                                   
mov esi, [edx + 0x20]                     
add esi, ebx                                 
xor ecx, ecx                                                 

Get_Function:                                                         

inc ecx                                   
lodsd                                           
add eax, ebx                                     
cmp dword [eax], 0x50746547                                   
jnz Get_Function                                                       
cmp dword [eax + 0x4], 0x41636f72                         
jnz Get_Function                                                       
cmp dword [eax + 0x8], 0x65726464                         
jnz Get_Function                                                       
mov esi, [edx + 0x24]                       
add esi, ebx                                 
mov cx, [esi + ecx * 2]                       
dec ecx                                                               
mov esi, [edx + 0x1c]                       
add esi, ebx                                 
mov edx, [esi + ecx * 4]                 
add edx, ebx                           

xor ecx, ecx                                         
push ebx                                     
push edx                               
push ecx                                               
push 0x41797261                                             
push 0x7262694c                                             
push 0x64616f4c                                                 
push esp                                         
push ebx                                   
call edx                                       

add esp, 0xc                                       
pop ecx                                             
push eax                                   

xor eax, eax
mov ax, 0x6c6c
push eax
push 0x642e3233
push 0x72657375
push esp                                     
call [esp + 16]
add esp, 12
push eax                               

xor eax, eax
mov eax, 0x2341786f
push eax
sub dword [esp + 3], 0x23
push 0x42656761
push 0x7373654d
push esp                                   
push dword [esp + 16]
call [esp + 28]
add esp, 12
push eax                               

xor eax, eax
mov eax, 0x23333231
push eax
sub dword [esp + 3], 0x23
push esp

xor eax, eax
mov eax, 0x23313233
push eax
sub dword [esp + 3], 0x23
push esp

push 0x20
push dword [ESP + 4]
push dword [ESP + 16]
xor eax, eax
push eax
call [ESP + 32]
add ESP, 16

Как видите, шеллкод заканчивается инструкцией add ESP, 16.
В дебаггере после исполнения лежит мусор, и приложение, куда инжектился шеллкод - тупо вылетает.
Пробовал получать EP приложения, и после исполнения добавить: jmp 0x(EP), но толку от этого = 0, ибо исполнение шло в отдельном потоке.

Вопрос к тем, кто как и я, а может и больше, занимается программированием на С++. Новичков или скрипт-кидди прошу не отвечать в теме.
Исполняю шеллкод через CreateRemoteThread
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
695
то управление никуда не возвращается
а куда оно должно возвратиться,?
В конце вообще что-то непонятное творится - PUSHей много, а POPов нет ниодного. Ведь add esp,16 очищает только последние 4-аргумента, а остальные лежат там мусором. Попробуй закоментировать 4-последних пуша перед call, а в конце сделать add esp,20 (хотя вызываемая MessageBox сама должна очистить свои параметры).

Обычно, перед тем-как запустить свой шел, основной тред клиента останавливают по SuspendThread(), а после - продолжают его по ResumeThread(). Шелл никуда не должен возвращать управление, а по окончании вообще лучше сделать себе харакири.
 
07.08.2020
10
2
BIT
0
а куда оно должно возвратиться,?
В конце вообще что-то непонятное творится - PUSHей много, а POPов нет ниодного. Ведь add esp,16 очищает только последние 4-аргумента, а остальные лежат там мусором. Попробуй закоментировать 4-последних пуша перед call, а в конце сделать add esp,20 (хотя вызываемая MessageBox сама должна очистить свои параметры).

Обычно, перед тем-как запустить свой шел, основной тред клиента останавливают по SuspendThread(), а после - продолжают его по ResumeThread(). Шелл никуда не должен возвращать управление, а по окончании вообще лучше сделать себе харакири.
Не вижу смысла комментировать 4 последних пуша, ибо они как раз нужны для инициализации аргументов под вызов функции.
Последнее не совсем понял. Т.е перед вызовом шелла (CreateRemoteThread) выполнить SuspendThread, исполнить шелл, а потом ResumeThread? Или же заморозить перед внедрением шелла?
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
695
Не вижу смысла комментировать 4 последних пуша,
это ясно, но тогда для чего предыдущие 5-пушей и кто их будет очищать?
Или же заморозить перед внедрением шелла?
без разницы кто будет этим заниматься - лишь-бы остановить клиента, чтобы шелл потом возвратил управление опять ему.

Например CreateRemoteThread() в пятом параметре "lpParameter" может передавать аргумент твоему шеллу - пусть инжектор передаёт в нём дексриптор клиентского треда, а ты внутри шелла останавливай его.
 
Последнее редактирование:
07.08.2020
10
2
BIT
0
это ясно, но тогда для чего предыдущие 5-пушей и кто их будет очищать?

без разницы кто будет этим заниматься - лишь-бы остановить клиента, чтобы шелл потом возвратил управление опять ему.
Сделал функцию для манипуляции с потоком:

Код:
BOOL ManipulateThread(DWORD pid, bool suspend) {
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    THREADENTRY32 te32;
    te32.dwSize = sizeof(THREADENTRY32);
    if (hSnap != NULL) {
        if (Thread32First(hSnap, &te32)) {
            do {
                HANDLE hThreadSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

                THREADENTRY32 threadEntry;
                threadEntry.dwSize = sizeof(THREADENTRY32);

                Thread32First(hThreadSnapshot, &threadEntry);

                do
                {
                    if (threadEntry.th32OwnerProcessID == pid)
                    {
                        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE,
                            threadEntry.th32ThreadID);

                        if (suspend) {
                            SuspendThread(hThread);
                        }
                        else {
                            ResumeThread(hThread);
                        }

                        CloseHandle(hThread);
                    }
                } while (Thread32Next(hThreadSnapshot, &threadEntry));

                CloseHandle(hThreadSnapshot);
            } while (Thread32Next(hSnap, &te32));
        }
    }
   
    return FALSE;
}

Внедряю шеллкод, замораживаю поток, запускаю шеллкод, жду пока шеллкод закончит выполнение через WaitForSingleObject, а после размораживаю. Итог: всё равно краш, после того как нажму OK в окне MessageBox. Я полностью уверен, что это потому, что нужно вставить что-то в конец. Выглядит в дебаггере всё вот так:

Код:
....
008900A4   FF7424 10        PUSH DWORD PTR SS:[ESP+0x10]
008900A8   FF5424 1C        CALL DWORD PTR SS:[ESP+0x1C]
008900AC   83C4 0C          ADD ESP,0xC
008900AF   50               PUSH EAX
008900B0   31C0             XOR EAX,EAX
008900B2   B8 31323323      MOV EAX,0x23333231
008900B7   50               PUSH EAX
008900B8   836C24 03 23     SUB DWORD PTR SS:[ESP+0x3],0x23
008900BD   54               PUSH ESP
008900BE   31C0             XOR EAX,EAX
008900C0   B8 33323123      MOV EAX,0x23313233
008900C5   50               PUSH EAX
008900C6   836C24 03 23     SUB DWORD PTR SS:[ESP+0x3],0x23
008900CB   54               PUSH ESP
008900CC   6A 20            PUSH 0x20
008900CE   FF7424 04        PUSH DWORD PTR SS:[ESP+0x4]
008900D2   FF7424 10        PUSH DWORD PTR SS:[ESP+0x10]
008900D6   31C0             XOR EAX,EAX
008900D8   50               PUSH EAX
008900D9   FF5424 20        CALL DWORD PTR SS:[ESP+0x20]
008900DD   83C4 10          ADD ESP,0x10
008900E0   0000             ADD BYTE PTR DS:[EAX],AL
008900E2   0000             ADD BYTE PTR DS:[EAX],AL
008900E4   0000             ADD BYTE PTR DS:[EAX],AL
008900E6   0000             ADD BYTE PTR DS:[EAX],AL
008900E8   0000             ADD BYTE PTR DS:[EAX],AL
008900EA   0000             ADD BYTE PTR DS:[EAX],AL
008900EC   0000             ADD BYTE PTR DS:[EAX],AL
008900EE   0000             ADD BYTE PTR DS:[EAX],AL
008900F0   0000             ADD BYTE PTR DS:[EAX],AL
008900F2   0000             ADD BYTE PTR DS:[EAX],AL
008900F4   0000             ADD BYTE PTR DS:[EAX],AL
008900F6   0000             ADD BYTE PTR DS:[EAX],AL
008900F8   0000             ADD BYTE PTR DS:[EAX],AL
008900FA   0000             ADD BYTE PTR DS:[EAX],AL
008900FC   0000             ADD BYTE PTR DS:[EAX],AL
008900FE   0000             ADD BYTE PTR DS:[EAX],AL
00890100   0000             ADD BYTE PTR DS:[EAX],AL
00890102   0000             ADD BYTE PTR DS:[EAX],AL
00890104   0000             ADD BYTE PTR DS:[EAX],AL
00890106   0000             ADD BYTE PTR DS:[EAX],AL
00890108   0000             ADD BYTE PTR DS:[EAX],AL
...
Напрягает мусор. Ставлю бряк на call, после - на add ESP, 0x10, всё норм, не крашится, потом возобновляю работу и краш.
 
07.08.2020
10
2
BIT
0
Решено. Дело было в шеллкоде.
Спасибо @Marylin - " а по окончании вообще лучше сделать себе харакири. ". Выполнял ret, так же exit(0) но это всё закрывало именно процесс, а не поток.
Спустя день мучений - нашел ExitThread. Добавил в шеллкод ExitThread(0) и всё заработало!
 

sanek35

Member
10.08.2020
10
0
BIT
0
для простоты эксперементов в таких случаях можно вместо шел кода внедрить болванку размером с шелкод

nop
int 3
db 50 dup (90h)
nop
int 3

запустищь в отладчике и посмотришь как оно там шевелится :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!