![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вот вопросик для мастеров!
Василий2 © (2002-11-04 13:51:00)Как внедрить свою DLL в чужой процесс? Только внедрять НЕ с помощью ловушек! Знаю, что надо использовать функции OpenProcess, VirtualAllocEx, WriteProcessMemory, CreateRemoteThread...
paul_shmakov (2002-11-10 13:36:00) [1]"насчет CreateRemoteThread в Win9X: а как? что, руцями искать по сигнатурам и ты ды? впрочем, можно не отвечать, ибо вопрос - чистое баловство и любопытство %-) все равно нету у меня этих систем, дабы проверить."
у меня тоже этих систем нет, поэтому эта возможность уже не очень актуальна для меня. но если есть интерес, то можно поизучать:
http://www.anticracking.sk/EliCZ/export/RT.ZIP
http://madshi.net
оба пакета достаточно легко дизассемблируются. да и код там не очень длинный.
"можно ли предположить, что если я создаю процесс при помощи CreateProcess(blah-blah, CREATE_SUSPENDED, blah-blah), а потом делаю GetThreadContext, то в регистре EAX находится стартовый адрес процесса (т.е. корректно вычесленная EntryPoint из заголовка)?"
честно говоря, не знаю. и проверить негде. в любом случае - можно entrypoint и самостоятельно получить.
Ketmar (2002-11-09 19:13:00) [2]я понял. вопрос просто криво сформулировал. вы-таки все ответили. пошел кастрировать Кассандру %-)
насчет CreateRemoteThread в Win9X: а как? что, руцями искать по сигнатурам и ты ды? впрочем, можно не отвечать, ибо вопрос - чистое баловство и любопытство %-) все равно нету у меня этих систем, дабы проверить.
насчет кода: просто я его из этого форума когда-то скопировал, и забыл, у кого (ну лень мне было писать, а тут как раз валяется %-). а вдруг автор обидится? %-))
и еще вопрос: можно ли предположить, что если я создаю процесс при помощи CreateProcess(blah-blah, CREATE_SUSPENDED, blah-blah), а потом делаю GetThreadContext, то в регистре EAX находится стартовый адрес процесса (т.е. корректно вычесленная EntryPoint из заголовка)? для моего Win2K Advanced Server это так, а для других систем? не знаете, часом?
Satanas Nobiscum! 09-Nov-XXXVII A.S.
paul_shmakov (2002-11-09 18:44:00) [3]кстати, CreateRemoteThread в win9x/me тоже реализована на самом деле. только она из kernel32.dll не экспортируется :( способ определения ее точки входа ну очень извращенский. а то было бы приятно...
это так, к слову :)
paul_shmakov (2002-11-09 18:37:00) [4]2 Ketmar:
"пусть сам ищет, большему научится. %-)"
вот это правильно, но если человек сам не хочет учиться - можно ему помочь готовым - ему же хуже в будущем ;)
"кстати, вот этот кусочек вызывает у меня сомнения: hTh := CreateRemoteThread(hProcess, nil, 0, LoadLibraryProc, MemPtr, 0, ThreadID);
после того, как LoadLibraryA-таки выполнилась, куда оно вернется? не есть ли более верно потом вызывать ExitThread? в хэлпе написано, что процедура потока "обычно не завершается" (имеется в виду, что не достигает финального end). на всех ли системах корректно предположить, что после завершения оной процедуры будет возврат в туда, куда ExitThread посылает?"
брр... не совсем понял вашу мысль - видать работы в праздники сказывается :)
поэтому изложу так, как я это все вижу. надеюсь отвечу :)
упрощенно последовательность такая:
1) объект ядра "поток" создается посредством вызова CreateThread или CreateRemoteThread. происходит некая инициализация вроде выделения стека, едыб вызовов dllmain с DLL_THREAD_ATTACH у загруженных dll и т.п.
2) начинает выполнятся функция в контексте этого потока, адрес которой был передан в Create(Remote)Thread.
3) как только происходит возврат из этой функции, вызывается ExitThread. т.е. условно код такой:
// действие происходит в далекой галактике, где-то глубоко внутри ядра windows....
void DeepInternalStartThread(...., LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ....)
{
// .... bla-bla-bla
// .... bla-bla-bla
// .... bla-bla-bla
ExitThread(lpStartAddress(lpParameter));
}
4. все, потока уже почти нет. в процессе выполнения ExitThread выполняется какая-то деинициализация, вроде оповещения dll о DLL_THREAD_DETACH, удаление стека потока и т.д. объект ядра "поток" будет уничтожен когда закроются все ссылки на него.
исходя из этой примерной схемы никаких проблем не видно. да и нет их :)
код LoadLibrary выполняется, а когда она завершается - удаляется поток.
"на всех ли системах корректно предположить, что после завершения оной процедуры будет возврат в туда, куда ExitThread посылает?"
а ExitThread "никуда не посылает" :) поток - это же отдельная нить выполнения. она завершается вызовом ExitThread - соответственно, дальше уже никуда ничего переходить, возвращаться и посылать не будет, т.к. само выполнение кода прекращено.
"и вот этот вот код (подправленный %-) часом не ваш? а то не помню, у кого спионерил %-)"
:) может и мой. а что? на самом деле, авторство тут не так важно - можно даже сказать, что автор - microsoft, т.к. имея, определенную ms, структуру pe файла сложно написать этот код иначе - у всех он получается примерно одинаковый.
Ketmar (2002-11-09 18:00:00) [5]2paul_shmakov:
а я и спрашивал, ЗАЧЕМ человеку знать. если "для интересу" - баловство. пусть сам ищет, большему научится. %-)
кстати, вот этот кусочек вызывает у меня сомнения:hTh := CreateRemoteThread(hProcess, nil, 0, LoadLibraryProc, MemPtr, 0, ThreadID);
после того, как LoadLibraryA-таки выполнилась, куда оно вернется? не есть ли более верно потом вызывать ExitThread? в хэлпе написано, что процедура потока "обычно не завершается" (имеется в виду, что не достигает финального end). на всех ли системах корректно предположить, что после завершения оной процедуры будет возврат в туда, куда ExitThread посылает?
и вот этот вот код (подправленный %-) часом не ваш? а то не помню, у кого спионерил %-)
var
PDOSHeader: PImageDosHeader;
PNTHeader: PImageNtHeaders;
PImportDesc: PImageImportDescriptor;
dwProtect: DWORD;
PThunk: PImageThunkData;
dwNewProtect: DWORD;
dwAddressToIntercept: DWORD;
WasProtected, Ok: Boolean;
begin
Result := False;
if IsBadReadPtr(Pointer(ModuleHandle), SizeOf(TImageNtHeaders)) then Exit;
// check for correct DOS header
PDOSHeader := PImageDosHeader(ModuleHandle);
if (PDOSHeader^.e_magic <> IMAGE_DOS_SIGNATURE) then Exit;
// check for correct PE header
PNTHeader := PImageNtHeaders(DWORD(PDOSHeader) + DWORD(PDOSHeader^._lfanew));
if (PNTHeader^.Signature <> IMAGE_NT_SIGNATURE) then Exit;
PImportDesc := PImageImportDescriptor(DWORD(ModuleHandle) +
DWORD(pNTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
if (DWORD(PImportDesc) = DWORD(PNTHeader)) then Exit;
dwAddressToIntercept := DWORD(HookAddr);
while (PImportDesc^.Name <> 0) do
begin
PThunk := PImageThunkData(DWORD(ModuleHandle) + DWORD(PImportDesc^.FirstThunk));
while (PThunk^.ProcEntry <> nil) do
begin
if (DWORD(pThunk^.ProcEntry) = dwAddressToIntercept) then
begin
WasProtected := IsBadWritePtr(@pThunk^.ProcEntry, SizeOf(DWORD));
if WasProtected then
Ok := VirtualProtect(@PThunk^.ProcEntry, SizeOf(DWORD), PAGE_EXECUTE_READWRITE, dwProtect)
else
Ok := True;
if Ok then
begin
// WriteLn("!");
PThunk^.ProcEntry := OldProc;
Result := True;
end;
if Ok and WasProtected then
begin
dwNewProtect := dwProtect;
VirtualProtect(@pThunk^.ProcEntry, SizeOf(DWORD), dwNewProtect, dwProtect);
end;
end;
Inc(PChar(PThunk), SizeOf(TImageThunkData32));
end;
Inc(PChar(PImportDesc), SizeOf(TImageImportDescriptor));
end;
end;
Satanas Nobiscum! 09-Nov-XXXVII A.S.
paul_shmakov (2002-11-09 17:16:00) [6]2 Ketmar:
" внедрение DLL - баловство..... хотя какие, нафиг, обыкновенные задачи требуют внедрения своего кода в чужой процесс?!"
ну не скажите, мне, например, необходимо расширять функциональность приложений (чужих, без исходников) для выполнения тех функций, которые в них изначально не были заложены. например, есть задача функционирования некоего приложения в условиях повышенной секретности. необходимо, например, чтобы все файлы, которые удаляет это приложение в процессе работы, удалялись без возможности восстановления, не с помощью обычной DeleteFile, как было заложено изначально разработчиками. и т.п.
при интеграции унаследованных систем с новым программным обеспечением тоже такие задачи часто появляются.
Василий2 (2002-11-09 17:08:00) [7]paul_shmakov: Спасибо!
Ketmar (2002-11-09 17:00:00) [8]внедрение DLL - баловство. не вижу, для чего бы вы могли это применить. для обыкновенных задач (хотя какие, нафиг, обыкновенные задачи требуют внедрения своего кода в чужой процесс?!) хуков вполне хватает.
если вы учитесь ИЗ ЛЮБОПЫТСТВА - так читайте Рихтера, учите Си и переводите. всяко полезное дело. по дороге еще, возможно, что нибудь интересное узнаете. а если у вас срочная задача (шеф приказал, курсовик горит и ты ды) - тогда другой разговор. тогда я кинусь кодом, а потом уже растолкую, что неясно. потому как горит. поелику у вас не горит, значит - баловство. тон ваш мне не нравится, следовательно - не поделюсь.
зыж
и вообще - давайте сойдемся на том, что я не знаю и не умею этого делать.
Satanas Nobiscum! 09-Nov-XXXVII A.S.
paul_shmakov (2002-11-09 16:53:00) [9]
//
// внедрение dll в чужой процесс с помощью CreateRemoteThread.
// работать будет только там, где эта самая CreateRemoteThread реализована,
// а это nt/w2k/xp
// использовать так:
// loader.exe идентификатор_процесса полный_путь_и_имя_dll
// paul_shmakov@mail.ru
//
program loader;
{$APPTYPE CONSOLE}
uses
Windows, Messages, SysUtils;
function SetDebugPriv: Boolean;
var
Token: THandle;
tkp: TTokenPrivileges;
begin
Result := false;
if OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then
begin
if LookupPrivilegeValue(nil, PChar("SeDebugPrivilege"), tkp.Privileges[0].Luid) then
begin
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
end;
end;
end;
function Start(ProcessID: Cardinal; DllFileName: string): Boolean;
var
hProcess, hTh: THandle;
BytesWritten, ThreadID, DllNameLen: Cardinal;
LoadLibraryProc, MemPtr: Pointer;
ExitCode: DWord;
begin
Result := false;
//
// этот вызов нужен только для внедрения в системные процессы
// btw, нужны привилегии администратора
//
SetDebugPriv();
hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,
true, ProcessID);
if hProcess <> 0 then
begin
DllNameLen := Length(DllFileName) + 1;
MemPtr := VirtualAllocEx(hProcess, nil, DllNameLen, MEM_COMMIT, PAGE_READWRITE);
if MemPtr <> nil then
begin
if WriteProcessMemory(hProcess, MemPtr, PChar(DllFileName), DllNameLen, BytesWritten) then
begin
LoadLibraryProc := GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
hTh := CreateRemoteThread(hProcess, nil, 0, LoadLibraryProc, MemPtr, 0, ThreadID);
if hTh <> 0 then
begin
if (WaitForSingleObject(hTh, INFINITE) = WAIT_OBJECT_0) and
GetExitCodeThread(hTh, ExitCode) then
Result := ExitCode <> 0;
CloseHandle(hTh);
end;
end;
VirtualFreeEx(hProcess, MemPtr, 0, MEM_RELEASE);
end;
CloseHandle(hProcess);
end;
end;
var
ProcessID: Cardinal;
DllName: string;
begin
if ParamCount < 2 then
begin
WriteLn("usage: loader.exe process_id dll_full_path_and_name");
Exit;
end;
ProcessID := StrToInt(ParamStr(1));
WriteLn("process id: " + IntToStr(ProcessID));
DllName := ParamStr(2);
WriteLn("dllname: " + DllName);
if ProcessID <> 0 then
begin
if Start(ProcessID, DllName) then
WriteLn("success")
else
WriteLn("fail");
end;
end.
Василий2 (2002-11-09 16:05:00) [10]2Ketmar:
Верно! Я пришел к вам за помощью, только вы помочь не хотите. Или не хотите или не знаете...
О каком баловстве вы говорите??? Внедрение DLL - баловство? Я знаю как внедрять с помощью ловушек, хочу попробовать с помощью потоков. В чем собственно проблема? Как вас еще просить - не понимаю.
Ketmar (2002-11-09 15:02:00) [11]2Василий2:
а большая разница. код - МОЙ. и мне интересно, для чего он будет использован. если у вас реальная срочная задача - да. если просто баловство - обойдетесь как-нибудь. у другого попросите, как и предполагали. я понял - баловство. ну и вперед, балуйтесь дальше.
кстати, не мешало бы быть повежливей. это не я к вам пришел, прося взять у меня код, а вы ко мне, за помощью. вот и будьте столь любезны просить ВЕЖЛИВО. comprenez vous?
Satanas Nobiscum! 09-Nov-XXXVII A.S.
Василий2 (2002-11-09 13:52:00) [12]Ketmar -> Скажем так: какая тебе РАЗНИЦА? Ты ведь не спрашиваешь почему я хожу с теми девками, а не с теми. Зачем тебе какие-то причины? Научиться я хочу!
Что касается кода, то мне без разницы пришлешь ты мне его или нет, №1 или №3... В конце концов других попрошу. Умолять я никого не буду. Но если пришлешь, то буду благодарен.
Ketmar (2002-11-08 19:06:00) [13]скажем так: мне очень интересно знать, ЗАЧЕМ это вам. если причины мне покажутся достаточно важными, я пришлю код. это во-первых. во-вторых, код №1 работоспособен только на WinNT, код №2 проверялся только на Win2K и я не знаю, будет ли работать в других системах. короче говоря - welcome в мое мыло. возможно, специально для вас вырежу кусок из Кассандры.
зыж
можно и догадаться, что если написать мне правильное мыло, то будет людям счастье %-))
ззыж
не знаю, правда, как мой код коррелируется с Рихтером (не смотрел я его реализацию)... у меня (Win2K Advanced Server) - работает.
Satanas Nobiscum! 08-Nov-XXXVII A.S.
Василий2 (2002-11-08 17:51:00) [14]Если бы мне это было не важно, я бы не писал, а раз тебе жалко, то зачем вообще писать об этом???
Ketmar (2002-11-08 15:10:00) [15]ну и что, что Ц? перевести сложно? in a mater of fact, у меня есть, конечно, на эльфах, только я не дам. жадный я. %-) разве если только задача очень срочная и важная...
Satanas Nobiscum! 08-Nov-XXXVII A.S.
Xemax (2002-11-08 13:46:00) [16]Форум заглючил ;-))
Xemax (2002-11-08 13:41:00) [17].
Xemax (2002-11-08 13:40:00) [18]
Xemax (2002-11-08 13:40:00) [19]
Василий2 (2002-11-07 20:35:00) [20]Единственное плохо - код на C... :(