"Похоже, ты упрощенно понимаешь задачу." похоже я вообще запутался С форматами файлов и поисками функций прийтней разбираться было(в удовольствие), т.к. была инфа(Hard Windom), а с этими сранными апи хер чего найдешь
В принципе, Астерикс все изложил исчерпывающе. Нужно выделить память в чужом процессе функцией VirtualAllocEx, потом скопировать туда свой код, используя WriteProcessMemory. После этого можно создавать удаленный тред.
warsem Поиск по форуму по ключевому слову CreateRemoteThread и inject а также здесь кое-что можно полезное узнать http://www.codeproject.com/threads/winspy.asp
Остался последний вопрос: что такое чужой процесс? По названию предпологаю что это обсолютно другая запущенная прога. Так чтоль? Гы, както странно получаеться...
Чужой процесс - я имел ввиду Explorer.exe или какой другой, не важно (во время отладки лучше извращаться над каким-нибудь calc.exe, предварительно его запустив). Если бы на С, я б тебе готовый пример прислал. Хотя, наверное, ты хочешь сам до всего докопаться. Поэтому по-порядку: Находим PID процесса-жертвы по его имени: CreateToolhelp32Snapshot Process32First Process32Next Получаем его хендл: OpenProcess Выделяем в этом процессе память для нашего кода: VirtualAllocEx Копируем в эту память нашу функцию: WriteProcessMemory Теперь можно вызывать CreateRemoteThread и завершать свою программу.
warsem Тут в аттаче небольшой пример, с комментариями. Думаю разберешься. Народ, пока warsem разбирается объясните кто-нибудь, что за беда такая, тоже думаю, в тему, поэтому тут и спрошу (надеюсь, warsem не будет возражать): Первый вопрос. Есть RemoteProc. Почему я во многих примерах вижу в таких случаях (в таких процедурах) напропалую пишут в коде например так: invoke <Некоторая API ф-ция>, <некоторые параметры> и вроде у кого-то работает. А у меня не работает. Ведь стандартные dll Винды грузятся по одним и тем же адресам. Если я вызываю в своей процедуре API, например из kernell32, ведь и в моём пространстве, и в пространстве акцептора, который примет и будет исполнять код, адрес ф-ции одинаков. Почему необходимо сначала получить адреса, сохранить их и передать вместе с кодом акцептору, и оттуда вызывать mov eax, offset Func mov eax,[eax] call eax. И второй вопрос: Почему адреса некоторых ф-ций при получении их адреса через GetProcAddress не соответствуют нормальным адресам, соответственно попытка их вызова завершается падением программы. Например: Sleep для передачи её адреса в RemoteProc, пришлось вычислять в Dependens.exe и вводить вручную, а от GetProcAddress получаю совсем другой, вызов по которому - падает программа. В то же время для Beep GetProcAddress возвращает нормальный адрес. Обе из kernel32. Непонятно... Оба вопроса в аттаче можно отследить. 1629943537__tester.zip
cresta Первый вопрос ... Рассмотрим простую программу Код (Text): .386 .model flat,stdcall include windows.inc include kernel32.inc includelib kernel32.lib .code align 4 _start: invoke ExitProcess, 0 end _start в момент выполнения она выглядит так Код (Text): ...;; секция кода 00401000 /$ 6A 00 PUSH 0 00401002 \. E8 01000000 CALL <JMP.&kernel32.ExitProcess> 00401007 CC INT3 00401008 .-FF25 00204000 JMP DWORD PTR DS:[<&kernel32.ExitProcess>] ... ;; секция импорта 00402000 7C81CAA2 kernel32.ExitProcess ... обрати внимание, что до непосредственного обращения в kernel32.ExitProcess делается call на адрес 00401008, по которому расположен jmp, который в свою очередь использует адрес 00402000 для получения реального адреса kernel32.ExitProcess, а теперь подумай какие могут быть гарантии, что в чужом процессе используется подобная технология вызова API и что требуемые функции расположены по таким же адресам. адреса некоторых ф-ций при получении их адреса через GetProcAddress не соответствуют нормальным адресам Что такое "нормальный адрес"?
cresta Код (Text): invoke GetProcAddress,ebx,addr szBeep ;<-- адрес Beep ... invoke GetProcAddress,ebx,szSleep ;<-- адрес Sleep. Ни хрена не соответствует :( между этими строчками есть небольшая разница
q_q Да, уже понял, тоже в отладчик полез. А нельзя ли сделать, чтобы не через jmp вызывать функции? Ведь если системная dll, то она грузится по определенным адресам, и наверное можно высчитать конечный адрес ф-ции на стадии линковки и записать сразу адрес или нельзя так? Может какие опции для компилятора/линкера есть. А то получается, чтобы мало-мальски удобно было, необходимо грузить свою dll в процесс акцептора. А второй вопрос - просто пропустил addr: invoke GetProcAddress,ebx,addr szSleep и передавал первый дворд строки вместо её адреса На всякий случай опять приаттачу уже поправленный пример _2015557072__tester.zip
cresta А нельзя ли сделать, чтобы не через jmp вызывать функции? Можно, но придется переписать inc-файлы и отказаться от использования макроса invoke. Например, код Код (Text): .386 .model flat,stdcall includelib kernel32.lib extern _imp__ExitProcess@4 : dword ExitProcess textequ <_imp__ExitProcess@4> .code align 4 _start: push 0 call ExitProcess end _start превращается в Код (Text): ... 00401000 6A 00 PUSH 0 00401002 FF15 00204000 CALL DWORD PTR DS:[<&kernel32.ExitProces>] .. 00402000 7C81CAA2 kernel32.ExitProcess ... Си'шный компилятор из VCT обходится без промежуточных jmp'ов, например, код Код (Text): #include <windows.h> #pragma comment(linker,"/MERGE:.rdata=.text") #pragma comment(linker,"/ALIGN:512 /SECTION:.text,EWRX") #pragma comment(linker,"/ENTRY:start") #pragma comment(linker,"/SUBSYSTEM:WINDOWS") #pragma comment(lib,"kernel32.lib") __declspec (naked) start (void) { ExitProcess(0); } в момент выполнения выглядит так Код (Text): ... 00400200 A2CA817C DD kernel32.ExitProcess 00400204 00000000 DD 00000000 00400208 00 DB 00 00400209 00 DB 00 0040020A 00 DB 00 0040020B 00 DB 00 0040020C 00 DB 00 0040020D 00 DB 00 0040020E 00 DB 00 0040020F 00 DB 00 00400210 6A 00 PUSH 0 00400212 FF15 00024000 CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>] 00400218 CC INT3 00400219 CC INT3 0040021A CC INT3 0040021B CC INT3 0040021C 44020000 DD 00000244 00400220 00000000 DD 00000000 00400224 00000000 DD 00000000 00400228 5A020000 DD 0000025A 0040022C 00020000 DD 00000200 00400230 00000000 DD 00000000 00400234 00000000 DD 00000000 00400238 00000000 DD 00000000 0040023C 00000000 DD 00000000 00400240 00000000 DD 00000000 00400244 4C020000 DD 0000024C 00400248 00000000 DD 00000000 0040024C AF00 DW 00AF 0040024E 45 78 69 74 50 72 6F 63 65 73 73 00 ASCII "ExitProcess",0 0040025A 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00 ASCII "KERNEL32.dll",0 ...
vinnie_pooh Охренеть, я о таком и не думал! Эт получаеться что добрый експлорер будет такие мерзости делать, а моя добрая прога просто выгружаться. Ха-ха-ха! Я в экстазе, хочу енто сделать. Мне так стало смешно от этой идеи, честно (ушел писать...)
q_q Собственно именно код компилятора си и сбил с толку (это о jmp). Асм-код давно в отладчике не смотрел, автоматом решил, что также напрямую адрес, как и в си-коде. Отсутствие invoke не беда, а вот инклюды переделывать, собирать все эти _imp__ExitProcess@4, не очень наверное приятно. Наверное для такого рода внедрителей код лучше сразу тогда на C++ писать. Без сишных либ, естественно, только API. Только будут ли тогда все адреса если их много, компактно лежать в DS.
Для этого есть утилита \masm32\tools\L2EXTIA\L2extia.exe А вообще мне не понятно что за надуманную проблему вы обсуждаете
cresta решил, что также напрямую адрес, как и в си-коде Прямого адреса в коде нет ни в Си, ни Ассемблере. Избавление от jmp'ов влияет только на размер исполняемого кода, но ни избавляет от необходимости определять адреса api. Asterix мне не понятно что за надуманную проблему вы обсуждаете Проблема в эффективном определении адресов api для потока внедряемого в адресное пространство чужого процесса.
Asterix, q_q Речь не о прямом адресе как таковом, допустим Call 78F09571 а о том, что не занимаясь этими изменениями инклюдов, можно сделать Call dword ptr[00401000] а о самом содержании этого dword ptr позаботится VС. И мне нет необходимости вызывать GetProcAddress/LoadLibrary для каждой используемой ф-ции/библиотеки раздувая код и провоцируя неявные ошибки, на одну из которых я уже попался (элементарная опечатка). Если vc++ выдаст мне готовый dword ptr, и готовый call dword ptr[], которые не изменятся в процессе загрузки модуля в память, то это будет хорошо. К утилитам вроде L2extia.exe и т.п. почему-то особого доверия нет. Почему - не знаю, но нет.
q_q Адрес чего, GetProcAddress? Речь о remote процессе? Код, который предполагается юзать в удаленном процессе заранее настраивается потом копируется в удаленный процесс уже настроенный. Или, если предполагается юзать самонастраивающийся код, то по крайней мере адрес GetProcAddress/LoadLibrary можно ему передать, а дальше пишется процедура поиска нужных API, адреса найденных API забиваются в табличку, вызов API соответственно будет происходить через эту табличку. cresta Ну и зря, в ней багов точно меньше чем в твоем коде , по крайней мере я на них не наткнулся. Можешь сам написать скрипт на каком-нибудь скриптовом языке perl, PHP, .. Я давно использую переделанные таким способом инклуды, была только одна проблема, какой-то конфликт имен в одной из стандартных структур, пришлось что-то переопределить в коде, не помню уже что %)
Уже посчитано их количество и проведен сравнительный анализ? )) После этого уж точно не буду пользоваться