Как да стартирате PE изображение, без да свързвате kernel32.dll и ntdll.dll

Опитах се да напиша peloader. Първо зареждам изпълнимото изображение и всички зависими от него dll (включително kernel32.dll и ntdll.dll) в паметта, обработвам цялата адресна таблица за импортиране, пренаписвам всички данни, които се нуждаят от преместване.

След това извиквам EntryPoint на всички изображения по ред. Получавам код за връщане 0 от EntryPoint на ntdll.dll, но kernel32.dll връща 0xC0000000. Когато се опитах да извикам EntryPoint на изпълнимия образ, програмата се срина.

Знам, че Windows системата вече зарежда ntdll.dll и kernel32.dll в паметта на процеса, когато процесът е създаден. Въпросът ми е как мога да заредя друго копие на ntdll.dll и kernel32.dll в паметта и да свържа моя модул с копията.

Правя си експеримент: 1. копирам ntdll.dll -> a.dll

  1. копирайте kernel32.dll -> b.dll
  2. модифицирайте PE файл с изображение b.dll, за да не зависи от ntdll.dll, а от a.dll
  3. напишете проста програма a.exe и модифицирайте PE файла с изображение a.exe, за да не зависи от kernel32.dll, а от b.dll
  4. стартирайте a.exe и програмата се срина

Възможно ли е да накарате a.exe да работи правилно?

Това е първият ми въпрос относно препълването на стека, съжалявам за лошия ми английски. Благодаря.


person cnzjnblxj    schedule 20.09.2011    source източник
comment
Наличен ли е кодът? Наскоро си мислех да направя същото. Що се отнася до въпроса ви, вероятно се проваля поради същата причина, поради която се проваля, когато се опитате да извикате ntdll!LdrLoadDll за kernel32 от собствено приложение -- kernel32 се опитва да се свърже с csrss и не успява.   -  person avakar    schedule 20.09.2011
comment
Добавям твърде много информация за отстраняване на грешки в моя код, така че е наистина мръсен. Ще преработя кода си по-късно, ако мога да реша проблема.   -  person cnzjnblxj    schedule 20.09.2011
comment
Може също да искате да извлечете източници на reactos reactos.org/en/index.html и разгледайте как имплементират CreateProcess. Имайте предвид, че след създаването на процесния обект те информират csrss за новия процес. Едва тогава създават новата нишка. Те също така не извикват входни точки, вместо това те изпращат чрез kernel32 thunk. Ядрото на Windows 7 стартира първата нишка в ntdll!__RtlUserThreadStart, която се грижи за инициализацията и в крайна сметка извиква изпълнимата входна точка.   -  person avakar    schedule 20.09.2011
comment
Благодаря много. Наистина е мило от ваша страна. Ще приема съвета ви и ще проверя моята ситуация. Благодаря ти много.   -  person cnzjnblxj    schedule 20.09.2011
comment
ако в крайна сметка искате да поставите кода си в github или някъде и да оставите връзка тук, може да ми е интересно да го разгледам.   -  person avakar    schedule 20.09.2011


Отговори (3)


Не мисля, че можеш да направиш това. Kernel32.dll и ntdll.dll, AFAIK не могат да се преместват. Тоест, MS премахна информацията за преместване от тях, защото, тъй като те вече са заредени във всеки процес, присвоените им адреси са винаги налични, по дизайн.

Така че, ако се опитате да ги заредите на различен адрес, добре, те ще се сринат. Теоретично бихте могли да опитате да възстановите информацията за преместването им... но не бих заложил на това.

Моят въпрос на свой ред е: защо не можете да използвате предварително заредения kernel32/ntdll? Защо смятате, че имате нужда от лични копия? Както виждам, трябва да ги считате за API на системата и така да ги оставите на мира.

person rodrigo    schedule 20.09.2011
comment
ntdll.dll и kernel32.dll ДА имат информация за преместване. PE файлът с изображение съдържа записа в директорията за адрес и размер на таблицата за преместване на базата. Така че мисля, че не това е целта. Можете да копирате ntdll.dll -› a.dll и да използвате LoadLibrary(a.dll), за да го заредите. Можете да получите манипулатор, различен от ntdll.dll. Някой може да инжектира dll в моя процес и да закачи системните ми повиквания, така че може да получа грешна информация за хардуера и т.н. Целта ми сам да заредя системни dll е само един от начините да предотвратя (или просто да не го направя твърде лесно) този вид кука. Съжалявам за лошия ми английски. - person cnzjnblxj; 20.09.2011
comment
това не е съвсем вярно, kernel32 и ntdll могат да се преместват, но само при рестартиране на системата (това е от ASLR) - person Necrolis; 20.09.2011
comment
О, прав си, в моя XP те наистина имат раздел .reloc, пълен с записи... Работата е там, че някак си спомням, че го нямат, може би в стара версия на Windows. - person rodrigo; 20.09.2011

Във Visual Studio поставете в свойствата на проекта linker->input->Ignore All default libraries до да. След това в c++->Code Generation->Basic Runtime Check по подразбиране (за да избегнете свързване в __RTC_*. След това в linker->Advanced->Entry Point указвате функция във вашия проект, която искате да бъде извикана при стартиране на програмата.

Създайте всичко и трябва да имате програма, която не е свързана с никоя библиотека, включително c-runtime.

person Community    schedule 20.09.2011
comment
Не описах въпроса толкова ясно, но все пак ви благодаря. - person cnzjnblxj; 20.09.2011

Ако искате да използвате своя собствена версия на ntdll.dll (a.dll) във вашия код, тогава можете да прочетете dll чрез Readfile() и да анализирате PE структурите, които да използвате във вашия код. например: можете да анализирате таблицата с имена за експортиране, таблицата с поредни номера за експортиране и таблицата с адреси за експортиране, за да намерите указатели към експортираните функции и да използвате същите във вашия изпълним файл.

person Saurabh    schedule 03.03.2012