NT LPC 20090414
Това http://www.zezula.net/en/prog/lpc.html е статията която чаках от няколко години.
LPC (Local Procedure Call) е начин за IPC под Windows който обаче не е много добре документиран в MSDN, но се използва масово за комуникация от системните файлове на Windows.
Това отваря нови врати в изследването на Windows поне за мен.
LPC (Local Procedure Call) е начин за IPC под Windows който обаче не е много добре документиран в MSDN, но се използва масово за комуникация от системните файлове на Windows.
Това отваря нови врати в изследването на Windows поне за мен.
x64 Flash .Net 20090414
Актуален проблем.
Правим програмка на .Net, слагаме един WebBrowser, тестваме и всичко работи.
ОБАЧЕ на една конкретна машина страницата не се визуализира поради проблем. След няколко дена се разбира че машината е Vista64, пробваме и действително има проблем - Flash не се показва.
Анализ - оказва се че .Net когато работи на 32 битова ОС си зарежда коректно 32 битовия Internet Explorer където има Flash Player. На 64 битова ОС - .Net framework зарежда обаче 64 битов Internet Explorer където обаче Flash Player няма. Всъщност 64 битов Flash няма и това е корена на проблема.
Сега - задачата е как да спасим готовия .Net проект без цялостно преработване?
Решението е просто и ми беше подсказано оттук:
Getting net bots work x64 systems
Това указва на .Net framework да се зарежда 32 битовата версия (дори и на 64 битова ОС). Internet Explorer успява да зареди Flash и проекта е спасен - с цената на 4 часа четене и един, единствен ред написан по него.
Правим програмка на .Net, слагаме един WebBrowser, тестваме и всичко работи.
ОБАЧЕ на една конкретна машина страницата не се визуализира поради проблем. След няколко дена се разбира че машината е Vista64, пробваме и действително има проблем - Flash не се показва.
Анализ - оказва се че .Net когато работи на 32 битова ОС си зарежда коректно 32 битовия Internet Explorer където има Flash Player. На 64 битова ОС - .Net framework зарежда обаче 64 битов Internet Explorer където обаче Flash Player няма. Всъщност 64 битов Flash няма и това е корена на проблема.
Сега - задачата е как да спасим готовия .Net проект без цялостно преработване?
Решението е просто и ми беше подсказано оттук:
Getting net bots work x64 systems
CorFlags FILE.exe /32BIT+ /ForceТова указва на .Net framework да се зарежда 32 битовата версия (дори и на 64 битова ОС). Internet Explorer успява да зареди Flash и проекта е спасен - с цената на 4 часа четене и един, единствен ред написан по него.
debugging time 20090402
"Две седмици дебъг спестяват три часа четене на документация!"
Колко мъдро казано. Затова мразя да скачам направо в новите проекти без да съм прочел грам ред.
Публикувано от Петър Николов
в Програмиране Коментари: (0)
Проследявания: (0)
Маркери, дефинирани към тази статия: jokes, programming
Temporary FileSystem 20090324
Концепцията на Linux за tmpfs ми харесва. Реално прави се файлова система която се намира в оперативната памет и при изключване на захранването цялата информация изчезва (всъщност не е и необходима). Така може да се използва RAM паметта за по-интензивни операции които да се записват на файловата система след изпълнение на дейноста.
Досега живях с илюзията че подобно нещо може да се реализира под Windows само ако е направено като RAM DISK, но се сетих че има и заобиколен начин.
CreateFile има два много специфични параметри - FILE_ATTRIBUTE_TEMPORARY и FILE_FLAG_DELETE_ON_CLOSE. При използването им съдържанието целия файл ще бъде съхранен в оперативната памет без следа на диска с две изключения - името му ще бъде някъде на диска и при изчерпване на паметта може да бъде временно съхранен на диска.
Това е и един много хитър трик с който 32 битови приложения могат да адресират повече от 2GB RAM без прекомпилация.
Отделно може се използва при декодиране на данни - на диска са записани кодирани и/или компресирани. С прост код се декомпресират/декодират във временен файл и който после се използва директно от паметта.
Досега живях с илюзията че подобно нещо може да се реализира под Windows само ако е направено като RAM DISK, но се сетих че има и заобиколен начин.
CreateFile има два много специфични параметри - FILE_ATTRIBUTE_TEMPORARY и FILE_FLAG_DELETE_ON_CLOSE. При използването им съдържанието целия файл ще бъде съхранен в оперативната памет без следа на диска с две изключения - името му ще бъде някъде на диска и при изчерпване на паметта може да бъде временно съхранен на диска.
Това е и един много хитър трик с който 32 битови приложения могат да адресират повече от 2GB RAM без прекомпилация.
Отделно може се използва при декодиране на данни - на диска са записани кодирани и/или компресирани. С прост код се декомпресират/декодират във временен файл и който после се използва директно от паметта.
Downgrade MSVC 2008 to 2005 20090323
Ако MSVC 2005 откаже да зареди проект от 2008 все пак има решение:
#! /bin/sh -e
# This script downgrades MSVC 2008 projects to MSVC 2005 projects, allowing
# people with MSVC 2005 to open them. Otherwise, MSVC 2005 simply refuses to
# open projects created with 2008. We run this as part of our release process.
# If you obtained the code direct from version control and you want to use
# MSVC 2005, you may have to run this manually. (Hint: Use Cygwin or MSYS.)
for file in .sln; do
echo "downgrading $file..."
sed -i -re 's/Format Version 10.00/Format Version 9.00/g;
s/Visual Studio 2008/Visual Studio 2005/g;' $file
done
for file in .vcproj; do
echo "downgrading $file..."
sed -i -re 's/Version="9.00"/Version="8.00"/g;' $file
done
# Yes, really, that's it.
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-а все някак ще се оправи.
За моя съжаление това беше само началото на проблемите ми. Следва продължение...
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.
« предишна страница
(Страница 1 от 1, общо 8 статии)
следваща страница »
