WinNT

11 отговора 560 прегледа
#1

WinNT

Самомодифициращ се код за WinNT, как да стане?

Отговор
в отговор на Alex #2

Re: WinNT

(towa e za VC++)
predpolagam che triabwa w module definition file da kajesh
che CODE sectiona e ima klas WRITE
ili w opciata na linkera /SECTION:CODE,W
i po princip ne sym se opitwal da go prawia, samo si poglednah MSDN ;)
dopuskam che i runtime moje da se smeni...?
ama ne mi se rowi poweche iz MSDN :)

Отговор
в отговор на Alex #3

Re: WinNT

VirtualQuery()/VirtualProtect() - трябва да смениш protection-а на страницата.

подводни камъни - 2 броя:
1. да не забравиш да извикаш FlushInstructionCache()
2. ако ползваш Visual C - много внимавай с инкременталния линкер на Microsoft. работа е там че адреса на функцията който ще ти върне не е истинския адрес, а адрес на thunk към нея - jmp _real_address_of_function.
така че или по на "едро" трябва да сменяш permission-ите на страниците (тоест на достатъчно голям регион за да си сигурен че се хваща реално функцията която искаш да промениш) или да махнем инкрементал линк-ването.

това е.

Отговор
в отговор на _ #4

Re: WinNT

Немисля,че горното(VirtualQuery()/VirtualProtect()) ще помогне да променям динамично инструкциите в сегмента за код.Работата е в това ,че под MS DOS чрез int 03h мога да доведа нещата до това че да се изпълни не тази поредица от инструкции която се очаква ако се дезасемблира кода(от делно че мога да хвана и самото дезасемблиране!).От както Intel въведе в 80286 защитения режим на работа на процесора ,директното добиране до прекъсванията и промяната на адреса който трябва да получи управлението(след настъпване на съответното прекъсване) са невъзможни.Но както MS DOS така и MS WINDOWSNT имат порядъчно количество недокументирани прекъсвания/функции.Така че ако някой знае как може да се постигне СМК с легални средства или с недокументиорани функции нека да каже.

Отговор
в отговор на Alex #5

Ring 0

[линк]

rgrdz:
bofh

Обаче дали резултата, ще оправдае вложеното време?

И не е ли по лесно да напишеш свой user32.dll, който да прави - *каквото искаш да прави* и освен това

LoadLibrary
GetProcAddress
FreeLibrary

към оригиналният, преименуван на dumb32.dll, като посредата имаш dup(xxx) за да постигнеш размера на оригиналният. Като имаш в предвид, че посочения файл се локва от OS-a трудно може да бъде сканиран от AV software. А може да ползваш и native api за да подменяш файловете по време на boot процеса.

bofh

Редактирано от bofh на

Отговор
в отговор на Alex #6

Re: WinNT

хм.. примерче.


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
__declspec (naked) int func(void)
{
__asm
{
mov eax, 0xDEADBEEF
ret
}
}
int main( void )
{
DWORD dwOld;
VirtualProtect( func, 4096, PAGE_EXECUTE_READWRITE, &dwOld );
FlushInstructionCache( GetCurrentProcess(), func, 4096 );

*(DWORD*)func = 0x90909090;
*((BYTE*)func+4) = 0x90;
return func();
}


всъщност Windows прави PAGE_EXECUTE_WRITECOPY.

както се вижда в eax няма да се появи очакваното 0xDEADBEEF.

в Win32 си няколко начини за динамична промяна хода на програмата (които общо взето са един и същ начин), в момента се сещам за:
1. закачаш се като debugger, за друг процес - можеш да му правиш какво ли не.
2. Get/SetThreadContext на нишка от твоето приложение, можеш да смениш регистрите, включително и EIP и ESP - така можеш да бутнеш изпълнението в съвсем неочаквана посока.
3. structured exception handling - примерно пишеш невалидни инструкции, процесора raise-ва exception, хващаш си exception-a в exception filter-a подменяш каквото си искаш в зависимост от регистрите (предварително намислени от теб преди да изпълниш невалидната инструкция) и правиш EXCEPTION_CONTINUE_EXECUTION за да се върнеш там където си бил (или пък на друго място, ако си променил и CONTEXT структурата).
прехващането на exception-a можеш да направиш и в kernel mode - инсталираш си драйвер, хващаш в IDT - int 6 (което е invalid opcode за интелските процесори) и после в зависимост от регистрите можеш да променяш нещо в кода или да смениш EIP-то на съвсем друго място в програмата. При постъпково изпълнение с user mode debugger след изпълнението на невалидната инструкция програмата просто си тръгва, оставяйки debugger-a в известно недоумение - къде отиде EIP-то. Дори и със SoftICE да debug-ваш резултатът е същия - правиш step и програмата се юрва неизвестно откъде. Със SoftICE-то обаче можеш да сложиш breakpoint на int 6 и ще изловиш каква е коварната тактика.

и ти ли Бруте, защита ще пишеш...

а недокументираните неща в WinNT не са чак толкова много, имам предвид не толкова много, че да останат такива дори и след упорит reverse engeneering.

Отговор
в отговор на _ #7

ops..

FlushInstructionCache() е по-добре да е след промяната:

*(DWORD*)func = 0x90909090;
*((BYTE*)func+4) = 0x90;

макар, че и така както е написано би трябвало да стане..

Отговор
в отговор на _ #8

Re: ops..

Поместеният код изобщо не работи както би трябвало.
Следващите два реда код замазват таблицата на скоковете към функции.И следователно скок към func() не се извършва.Това може да се провери като се дезасемблира кода и се наблюдава паметта в една околност на кода на функцията.
*(DWORD*)func = 0x90909090;
*((BYTE*)func+4) = 0x90;

А ако се опита самата функция да промени кода в тялото си чрез код като.
__declspec (naked) int func(void)
{
__asm
{
mov ebx,offset a00
mov byte ptr cs:[ebx],0x90

}
a00:
__asm
{
inc eax
ret
}
}
То се стига до съобщение за грешка:
Unhandled exeption in CMK000.exe:0x00000005: A ccess Violation.

Въобще цялата идея свързана с VirtualProtect(func,4096,PAGE_EXECUTE_READWRITE,&dwOld); е обречена на неуспех.

Отговор
в отговор на bofh #9

Re: Ring 0

Мисля че адресът ще свърши работа.
Но по въпроса в dll's нищо не разбрах.

Отговор
в отговор на Alex #10

Великото Изкуство на Светлината и Сянката

>>>>>>>>>>>>>>>>
Поместеният код изобщо не работи както би трябвало.
Следващите два реда код замазват таблицата на скоковете към функции.И > следователно скок към func() не се извършва.Това може да се провери като > > се дезасемблира кода и се наблюдава паметта в една околност на кода на > функцията.
*(DWORD*)func = 0x90909090;
*((BYTE*)func+4) = 0x90;
<<<<<<<<<<<<<<<<

а инкременталния линкер махна ли както бях заръчал?
обзалагам се че не си.
и приличам ли на човек който ще пост-не програмен код, който да не е бъде проверен?


>>>>>>>>>>>>>>>>>
А ако се опита самата функция да промени кода в тялото си чрез код като.
__declspec (naked) int func(void)
{
__asm
{
mov ebx,offset a00
mov byte ptr cs:[ebx],0x90

}
a00:
__asm
{
inc eax
ret
}
}
То се стига до съобщение за грешка:
Unhandled exeption in CMK000.exe:0x00000005: A ccess Violation.
<<<<<<<<<<<<<<<<<<<<<<

естествено - ето това нещо: mov byte ptr cs:[ebx],0x90
ще хвърли exception-a защото използваш CS!! Ако погледнеш segment дескриптора на CS в LDT - в него няма такова нещо като права за писане (по точно чрез селектора към този дескриптор).
тоест сритва те защитата на процесора на още на ниво селектор/дескриптор - все още транслацията на адреса не е стигнала до страницирането и съответно да са в сила permission-ите която слагаме с VirtualProtect (те са на ниво страници).
CS регистъра си е за код и толкова - не можеш да пишеш чрез него. трябва да използваш DS - и двата дескриптора сочат към едни и същи виртуални адреси, така че няма проблем - отместванията спрямо CS и DS (и SS) са на един и също място.
с думи прости - напиши го просто така:
mov byte ptr [ebx],0x90
(или ако много държиш на явното упоменаване на регистъра - mov byte ptr ds:[ebx],0x90 )

>>>>>>
Въобще цялата идея свързана с VirtualProtect(func,4096,PAGE_EXECUTE_READWRITE,&dwOld); е обречена на неуспех.
<<<<<<

позволи ми да се усъмня...

Отговор
в отговор на _ #11

Re: Великото Изкуство на Светлината и Сянката

Прав си,прав си за всичко,как можах да се усъмня?
Но какъв е този инкрементален линкер?

Отговор
в отговор на Alex #12

incremental link

>>>>>>>>>
An incrementally linked program is functionally equivalent to a program that is nonincrementally linked. However, because it is prepared for subsequent incremental links, an incrementally linked executable (.EXE) file or dynamic-link library (DLL):

- Is larger than a nonincrementally linked program because of padding of code and data. (Padding allows the linker to increase the size of functions and data without recreating the .EXE file.)

- May contain jump thunks to handle relocation of functions to new addresses.

<<<<<<<<<<<<<<

обърни внимание на това последното.

във средата на Visual C дали да се използва incremental-ен линк се определя от Project /Settings -> tab Link -> Category General -> Link Incrementally
това променя опцията на линкера - /INCREMENTAL:{YES|NO}

за debug build-овете е по подразбиране /INCREMENTAL:YES което съчетано с опцията на компилатора - 'Program Database for Edit and Continue" (/ZI) дава възможност за:

>>>>>>>>
With Edit and Continue (a new feature in Visual C++ 6.0), you can make changes to your source code while the program is being debugged (with some limitations). You can apply code changes while the program is running or halted under the debugger.
<<<<<<<<<

което разбира се в общия случай е ценно...

Отговор