Мисъл на деня 20081031
De linqua stulta veniunt incommoda multa - Заради глупав език стават много неприятности.
Мисъл на деня 20081030
"Ако си на власт, трябва много да лъжеш, иначе народът няма да ти вярва за нищо!"Нинус Несторович
Мисъл на деня 20081024
Лъжата, която прилича на истина, не е по- добра от истината, която прилича на лъжа - Кабус Наме
Мисъл на деня 20081021
Mors nescit legem, tollit cum paupere regem - смъртта не знае закон, взема и царя, и бедняка.
Multos timere debet, quem multi timent. - От мнозина трябва да се страхува този, от когото мнозина се страхуват.
Напоследък много ми харесват всякакви такива латински мисли.
Delphi Shared Library 20081014
Преди време използвах Windows 98 и си бях направил любимите "образователни" програми когато изникна гигантски проблем.
Под 9X ядрата има област от паметта между 2Gb и 3Gb която е видима от всички програми. Там се качват повечето от библиотеките като Kernel32, User32, GDI32 и т.н. Когато моята програма направи кръпка върху Kernel32 в рамките на програмата кръпката работи, но когато се друга програма направи същото извикване следва моментален забив защото моя код не се намира в тази специфична област от паметта и в адресното пространство на другата програма го няма.
Тук следваше кратко проучване и се видя само че VisualC++ може да прави т.нар. shared sections и настройка на $IMAGEBASE над 2Gb размера (0x7FFFFFFF) под Delphi не може да се направи.
Така задачите станаха 2 - да направя секциите (всичките) shared и да настроя ImageBase над 2Gb. За щастие имах програма която зареждаше модула където трябва така че всичките настройки ги направих там.
Кратко разяснение - първия коментар е ImageBase. За мое огромно съжаление НЕ РАБОТИ (затова е и закоментарен), защото всички отмествания трябва наново да се направят (т.нар. rebasing). Следва пипането на атрибутите на секциите, тук по-принцип трябва да има някакво зареждане на PE файл и пипане на секциите му, но понеже съм мързелив съм настроил отместванията както на стандартна Delphi DLL. По-интересно е последното с ReBaseImage. Ако пряко се подаде нов ImageBase пак не работи - затова се прибягва до трик - вземам адреса на Kernel32 и казвам на библиотеката да се настрои спрямо него, а DLL loader-а все някак ще се оправи.
За моя съжаление това беше само началото на проблемите ми. Следва продължение...
Под 9X ядрата има област от паметта между 2Gb и 3Gb която е видима от всички програми. Там се качват повечето от библиотеките като Kernel32, User32, GDI32 и т.н. Когато моята програма направи кръпка върху Kernel32 в рамките на програмата кръпката работи, но когато се друга програма направи същото извикване следва моментален забив защото моя код не се намира в тази специфична област от паметта и в адресното пространство на другата програма го няма.
Тук следваше кратко проучване и се видя само че VisualC++ може да прави т.нар. shared sections и настройка на $IMAGEBASE над 2Gb размера (0x7FFFFFFF) под Delphi не може да се направи.
Така задачите станаха 2 - да направя секциите (всичките) shared и да настроя ImageBase над 2Gb. За щастие имах програма която зареждаше модула където трябва така че всичките настройки ги направих там.
procedure PatchLibrary(Filename: string);
var f: file of byte;
i: byte;
a,b,c,d: cardinal;
begin
AssignFile(f, Filename);
Reset(f);
// Seek(f,$136); i:=$23; write(f,i); i:=$81; write(f,i); //imagebase $81230000
Seek(f,$1FE); i:=$72; write(f,i); i:=$83; write(f,i);
Seek(f,$21F); i:=$70; write(f,i);
Seek(f,$226); i:=$72; write(f,i); i:=$83; write(f,i);
Seek(f,$247); i:=$D0; write(f,i);
Seek(f,$24E); i:=$72; write(f,i); i:=$83; write(f,i);
Seek(f,$26F); i:=$D0; write(f,i); i:=$83; write(f,i);
Seek(f,$297); i:=$D0; write(f,i); i:=$83; write(f,i);
a:=0; b:=0; c:=0; //d:=$8123000;
d:=GetModuleHandle('kernel32.dll');
ReBaseImage(PAnsiChar(Filename),nil,true,true,false,0,a,b,c,d,0);
closefile(f);
end;
Кратко разяснение - първия коментар е ImageBase. За мое огромно съжаление НЕ РАБОТИ (затова е и закоментарен), защото всички отмествания трябва наново да се направят (т.нар. rebasing). Следва пипането на атрибутите на секциите, тук по-принцип трябва да има някакво зареждане на PE файл и пипане на секциите му, но понеже съм мързелив съм настроил отместванията както на стандартна Delphi DLL. По-интересно е последното с ReBaseImage. Ако пряко се подаде нов ImageBase пак не работи - затова се прибягва до трик - вземам адреса на Kernel32 и казвам на библиотеката да се настрои спрямо него, а DLL loader-а все някак ще се оправи.
За моя съжаление това беше само началото на проблемите ми. Следва продължение...
TrimWorkingSet 20081013
procedure TrimWorkingSet;
var
MainHandle : THandle;
begin
MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID);
SetProcessWorkingSetSize(MainHandle,-1,-1);
CloseHandle(MainHandle);
end;
Преди време разработвах един проект когато ми обърнаха внимание че проекта изведнъж след тръгване се минимизира и после се връща в отново в нормално положение. Понеже проекта беше наследен и нямаше как да се преработи изоснови взех че махнах тази негова особенност. На следващия ден получих гневен мейл как съм махнал основна функция и да съм я върнел веднага. И аз си зачудих какво е толкова много специфицното на едно минимизиране-връщане.
Оказа се че Windows NT при минимизиране намаля размера на паметта изполвана от програмата. Пример пускам calc.exe в момента - използваната памет е 3684 k, минимизираме и програмата заема 508 k, възтановяване и 1552 k. Тази фукнция на операционната система ми беше неизвестна, но минимизирането и възстановяването ми беше доста досадно.
След няколко дена намерих горния код който върши подобна работа и без досадните миганки на програмата. Отделно кода е достатъчно гъвкав и може да се преработи и за VisualC++, Visual Basic, C++Builder и даже .Net.
На печелившите честито!
CreateProcessAsUser 20081013
Наложи ми се да да стартирам процес като друг потребител (който работи на същата машина) от service.
Та единствения вариaнт е CreateProcessAsUser който изисква обаче един token. Има доста начини да се вземе token, но голяма част от тях изискваха и паролата на потребителя с цел LoginUser което беше безумие.
Та лутайки се се сетих че и WinLogon някак си успява да стартира TaskMgr с акаунта на текущия потребител което е странно защото WinLogon работи на ниво System. Значи начини имаше. Стартирах набързо един WinDBG и видях как го правят.
Следва псевдо-код който прави подобна задачка:
Разяснение: Имаме стартиран процес от потребител USER. Услугата (service) ни работи на ниво System. Намираме процеса който работи под този потребител, отваряме го и му вземаме token. След което го дупликираме с важния (да се чете НАЙ-Важния) параметър и си извикваме като пичове CreateProcessAsUser без да знаем паролата на потребителя.
Всичко това естественно е прекрасно, но работи само под потребители с ранг Administrator и SYSTEM. На останалите не съм го тествал. Под обикновенни потребители НЕ РАБОТИ защото не може да се отвори процеса (още първия ред) поради ниски привилегии.
Кода който работи в WinLogon е подобен, но там го правят малко по-странно. Всичко това с tokens е подобно. Но там правят текущия thread да работи под зададения потребител (NtSetInformationThread) стартират процеса с CreateProcessAsUser, след което връщат привилегиите на зададения thread до предишните такива. За сега смисъла на тази врътка ми остава неразбран.
Та единствения вариaнт е CreateProcessAsUser който изисква обаче един token. Има доста начини да се вземе token, но голяма част от тях изискваха и паролата на потребителя с цел LoginUser което беше безумие.
Та лутайки се се сетих че и WinLogon някак си успява да стартира TaskMgr с акаунта на текущия потребител което е странно защото WinLogon работи на ниво System. Значи начини имаше. Стартирах набързо един WinDBG и видях как го правят.
Следва псевдо-код който прави подобна задачка:
OpenProcess
OpenProcessToken
DuplicateTokenEx (SecurityImpersonation) <- Най-важния параметър
CreateProcessAsUser
Разяснение: Имаме стартиран процес от потребител USER. Услугата (service) ни работи на ниво System. Намираме процеса който работи под този потребител, отваряме го и му вземаме token. След което го дупликираме с важния (да се чете НАЙ-Важния) параметър и си извикваме като пичове CreateProcessAsUser без да знаем паролата на потребителя.
Всичко това естественно е прекрасно, но работи само под потребители с ранг Administrator и SYSTEM. На останалите не съм го тествал. Под обикновенни потребители НЕ РАБОТИ защото не може да се отвори процеса (още първия ред) поради ниски привилегии.
Кода който работи в WinLogon е подобен, но там го правят малко по-странно. Всичко това с tokens е подобно. Но там правят текущия thread да работи под зададения потребител (NtSetInformationThread) стартират процеса с CreateProcessAsUser, след което връщат привилегиите на зададения thread до предишните такива. За сега смисъла на тази врътка ми остава неразбран.
CreateRemoteThread vs. CreateThread 20081013
Преди време се наложи да направя някаква форма на прехващане на основни функции на Windows с образователна цел.
Та едни от основните функции бяха CreateThread и CreateRemoteThread. В документациите функциите са описани доста добре, но реално ми направи впечатление че всичко води към NtCreateThread и в мен се породи въпроса - как тогава работят двете. След кратък размисъл и пускане на debugger истината лъсна наяве. Реално CreateThread НЯМА. Има само някавъв wrapper който извиква CreateRemoteThread, но параметъра hProcess се подава като 0xFFFFFFFF.
Та едни от основните функции бяха CreateThread и CreateRemoteThread. В документациите функциите са описани доста добре, но реално ми направи впечатление че всичко води към NtCreateThread и в мен се породи въпроса - как тогава работят двете. След кратък размисъл и пускане на debugger истината лъсна наяве. Реално CreateThread НЯМА. Има само някавъв wrapper който извиква CreateRemoteThread, но параметъра hProcess се подава като 0xFFFFFFFF.
Recycling 20081010
If you purchased $1,000 of shares in Delta Airlines one year ago, you will have $49.00 today.
If you purchased $1,000 of shares in AIG one year ago, you will have $33.00 today.
If you purchased $1,000 of shares in Lehman Brothers one year ago, you will have $0.00 today.
But, if you purchased $1,000 worth of beer one year ago, drank all the beer, then turned in the aluminum cans for recycling refund, you will have received $214.00.
Based on the above, the best current investment plan is to drink heavily & recycle.
Ето че значението на Recycling придоби ново значение...
« предишна страница
(Страница 1 от 1, общо 9 статии)
следваща страница »
