Очевидно, что LoadLibrary слишком «громкий» способ внедрения в другой процесс для антивирусного ПО. Подозрительный процесс, вирусный или заражённый вирусом, может воспрепятствовать внедрению в себя со стороны подобным способом одним из множества способов.
Вирусный процесс может запросто и от CreateRemoteThread защищаться (каждый новый поток, в том числе созданный удалённо, вызывает TLS callbacks и DllMain всех dll-ек, пока адрес грядущей передачи управления лежит себе на стеке), и каждые пять секунд сканировать всю свою память на предмет executable-страниц вне dll-ек (палевно, системные библиотеки себе такого не позволяют), и каждую секунду перечислять список потоков в своём процессе... Единственный выигрышный ход — не играть в эту игру и вообще не запускать свой код в контексте чужого процесса, всё остальное — противостояние щита и меча.
UPD: с VS2019 забавнее, для конкретно этого примера /Gy- переупорядочивает в порядке первого объявления, а не реализации. Соответственно, если мы, как добропорядочные сишники, вынесли внешние объявления в отдельный inject.h (чтобы не нарваться на ситуацию "реализацию поменяли, объявления в других файлах .c поменять забыли")
и рассчитываем, что в бинарнике они будут идти в таком же порядке и можно смело memcpy-ить всё это куда угодно... нас может спасти только инлайнинг всего подряд, потому что с /Gy- порядок этих функций будет RemoteThreadProc, EndOfRemoteThreadProc, DoSomethingUsefulButNotInlinable, а без него DoSomethingUsefulButNotInlinable, EndOfRemoteThreadProc, RemoteThreadProc (вряд ли стоит копипастить сюда третий ассемблерный листинг подряд только чтобы проиллюстрировать порядок; я бы дал ссылку на godbolt.org, но там управляющая система, судя по всему, не дизассемблирует бинарник, а просит листинг у компилятора через /Fa и не исключено, что ещё и переупорядочивает его потом).
С ключом /Gy- это ещё и от версии компилятора зависит. Вот, например, компилятор из Visual Studio 2010:
C:\temp\vs2010>cl /c /O2 /Gy- /I"E:\programs\compilers\Microsoft Visual Studio 10.0\VC\include" C:\temp\inject.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
inject.c
C:\temp\vs2010>dumpbin /disasm inject.obj
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file inject.obj
File Type: COFF OBJECT
_DoSomethingUseful:
00000000: 68 00 00 00 00 push offset ??_C@_0BD@GJCDPNPO@DoSomethingUseful?6?$AA@
00000005: E8 00 00 00 00 call _printf
0000000A: 59 pop ecx
0000000B: C3 ret
0000000C: CC int 3
0000000D: CC int 3
0000000E: CC int 3
0000000F: CC int 3
_EndOfRemoteThreadProc:
00000010: 68 00 00 00 00 push offset ??_C@_0BH@IKBAAHGF@EndOfRemoteThreadProc?6?$AA@
00000015: E8 00 00 00 00 call _printf
0000001A: 59 pop ecx
0000001B: C3 ret
0000001C: CC int 3
0000001D: CC int 3
0000001E: CC int 3
0000001F: CC int 3
_RemoteThreadProc:
00000020: 68 00 00 00 00 push offset ??_C@_0BC@EGMKFOBF@RemoteThreadProc?6?$AA@
00000025: E8 00 00 00 00 call _printf
0000002A: 68 00 00 00 00 push offset ??_C@_0BD@GJCDPNPO@DoSomethingUseful?6?$AA@
0000002F: E8 00 00 00 00 call _printf
00000034: 83 C4 08 add esp,8
00000037: C3 ret
Summary
30 .debug$F
6C .debug$S
2F .drectve
3C .rdata
38 .text
(тут, кстати, видно, что printf ещё была обычной внешней функцией). В VS2019 для конкретно этого примера ключ /Gy- дополнительно переупорядочивает функции в более ожидаемом порядке. Для более сложных примеров уже детально ковыряться надо (и перспектива получить ответ "ну конечно же никто не будет в столь системном коде столь творчески инстанцировать плюсовые шаблоны" не особенно вдохновляет), мне лень.
Сливали SP1. Это кодовая база ещё до пресловутого W32/Blaster с компанией и, соответственно, до субботникамесячника годичника безопасности в MS, после которого SP3 уже местами сильно другой продукт.
Кроме того, наверняка есть более эффективные алгоритмы решения этой задачи, но представленный результат непродолжительных раздумий тоже сойдёт для этого небольшого воскресного приключения.
Конечно, есть. Сумма делителей мультипликативна в смысле теории чисел: если n=ab и a,b взаимно просты, то сумма делителей n равна произведению сумм делителей для a и b. Так что достаточно посчитать суммы для степеней простых и перемножить:
std::vector<int64_t> arr;
arr.resize(n + 1, 1);
int64_t p;
for (p = 2; p * p <= n; p++) if (arr[p] == 1) {
int64_t ppow = p;
int64_t sum = 1;
do {
sum += ppow;
int64_t q, residue = 1;
for (int64_t q = ppow; q <= n; q += ppow, residue++)
if (residue == p)
residue = 0;
else
arr[q] *= sum;
ppow *= p; // no overflow here if n**(3/2) < 2**63; we get std::bad_alloc long before this otherwise
} while (ppow <= n);
}
for (; p <= n; p++) if (arr[p] == 1) {
for (int64_t q = p; q <= n; q += p)
arr[q] *= 1 + p;
}
std::cout << arr.back() << std::endl;
Просто перехватывать SEH-исключения на С и C++ можно было ещё с момента появления этих самых SEH-исключений в Windows 95, через синтаксис __try / __except / __finally.
Какие ещё «амбиции компиляторщиков»? В VC++ есть преобразование SEH -> C++ exception: _set_se_translator.
В Word просто пошли по другому пути: не делать сложных манипуляций при access violation — тем более, что если AV вообще произошло, то в данных вполне может быть каша, а получить документ с кашей намного неприятнее, чем потерять последний сеанс работы — а периодически делать временную копию, пока данные гарантированно целы, при AV вылетать, а после перезапуска предлагать её восстановить.
Отдельного внимания заслуживает использование регистра rdi. Вызывающий код обнуляет edi – половину rdi, а вызываемый код ДОВОЛЬНО НЕОЖИДАННО – использует наполовину обнуленный rdi.
«Всякие принтеры» и в винде могут работать в юзерспейсе через UMDF. Когда я последний раз проверял, UMDF-драйверы принудительно подписывать было не нужно.
В ...\Image File Execution Options\<filename>.exe\ можно создать значение "UseFilter"=dword:00000001 и произвольное количество подключей с произвольными именами, внутри подключей — значение "FilterFullPath"="C:\<полный путь к filename>.exe", тогда настройки будут браться из подключа с FilterFullPath, совпавшим с полным путём (если такого не нашлось, то, как и раньше, из самого IFEO\<filename>.exe\).
Если же входил, то ответом для данного i будет k – 1 + gi, где k — порядковый номер данного друга в оптимальном ответе.
Это же неправда. Контрпример: Малыш живёт на этаже 1000, рост Карлсона 1 (чтобы не заморачиваться с вопросами инициализации), на первом этаже друг роста 4, на втором — друг роста 998, на третьем — друг роста 1000, на четвёртом — друг роста 999, на каждом следующем этаже m — друг роста m+1. Оптимальная стратегия, очевидно, — две пересадки на первом и на третьем этажах. Если же поссориться с другом на третьем этаже, то g3=3 (если доступны только два первых этажа, придётся просить друзей на 2,998,999 этажах), k-1+g3=4, но Карлсон вполне может добраться за три пересадки, этажи 1,4,999.
Разная семантика inline. Программа из двух файлов. test1.c:
inline void f() {}
int main() { f(); return 0; }
test2.c:
void f() {}
Валидно в C, ошибка линковки в C++. Если второй файл убрать, то валидно в C++, ошибка линковки в C (точнее, программа не соответствует стандарту, и может быть ошибка линковки в зависимости от настроения компилятора — будет с gcc -O0, не будет с gcc -O2).
На Википедии есть пример с sizeof('x').
Молчаливое преобразование к/из void*, как выше уже привели пример, отнюдь не ограничивается «ручным» выделением памяти.
Ну а если смотреть на новые стандарты, то они вообще по-разному развиваются: _Bool вместо bool, float _Complex, всякие
#define mysqrt(X) _Generic((X), long double: sqrtl, default: sqrt, float: sqrtf)
Нельзя копировать код с помощью memcpy, всё намного сложнее
Вирусный процесс может запросто и от CreateRemoteThread защищаться (каждый новый поток, в том числе созданный удалённо, вызывает TLS callbacks и DllMain всех dll-ек, пока адрес грядущей передачи управления лежит себе на стеке), и каждые пять секунд сканировать всю свою память на предмет executable-страниц вне dll-ек (палевно, системные библиотеки себе такого не позволяют), и каждую секунду перечислять список потоков в своём процессе... Единственный выигрышный ход — не играть в эту игру и вообще не запускать свой код в контексте чужого процесса, всё остальное — противостояние щита и меча.
Нельзя копировать код с помощью memcpy, всё намного сложнее
UPD: с VS2019 забавнее, для конкретно этого примера /Gy- переупорядочивает в порядке первого объявления, а не реализации. Соответственно, если мы, как добропорядочные сишники, вынесли внешние объявления в отдельный inject.h (чтобы не нарваться на ситуацию "реализацию поменяли, объявления в других файлах .c поменять забыли")
в inject.c поместили реализации всех вспомогательных функций между этими двумя
и рассчитываем, что в бинарнике они будут идти в таком же порядке и можно смело memcpy-ить всё это куда угодно... нас может спасти только инлайнинг всего подряд, потому что с /Gy- порядок этих функций будет RemoteThreadProc, EndOfRemoteThreadProc, DoSomethingUsefulButNotInlinable, а без него DoSomethingUsefulButNotInlinable, EndOfRemoteThreadProc, RemoteThreadProc (вряд ли стоит копипастить сюда третий ассемблерный листинг подряд только чтобы проиллюстрировать порядок; я бы дал ссылку на godbolt.org, но там управляющая система, судя по всему, не дизассемблирует бинарник, а просит листинг у компилятора через /Fa и не исключено, что ещё и переупорядочивает его потом).
Нельзя копировать код с помощью memcpy, всё намного сложнее
С ключом /Gy- это ещё и от версии компилятора зависит. Вот, например, компилятор из Visual Studio 2010:
(тут, кстати, видно, что printf ещё была обычной внешней функцией). В VS2019 для конкретно этого примера ключ /Gy- дополнительно переупорядочивает функции в более ожидаемом порядке. Для более сложных примеров уже детально ковыряться надо (и перспектива получить ответ "ну конечно же никто не будет в столь системном коде столь творчески инстанцировать плюсовые шаблоны" не особенно вдохновляет), мне лень.
Нельзя копировать код с помощью memcpy, всё намного сложнее
Как скажете:
Нельзя копировать код с помощью memcpy, всё намного сложнее
Да ну?
Выживание Windows XP x32 на современных ПК c процессором Intel
AntiWPA, скорее всего.
На MDL говорят, что телефонная активация кейгенится без патчей forums.mydigitallife.net/threads/is-there-any-way-to-crack-decrypt-the-winxp-consumer-activation-system-to-generate-activation-ids.80133/page-2#post-1640340, но готового кейгена не выкладывают.
Выживание Windows XP x32 на современных ПК c процессором Intel
субботникамесячникагодичника безопасности в MS, после которого SP3 уже местами сильно другой продукт.Microsoft начала внутреннее расследование утечки исходных кодов Windows XP и Windows Server 2003
Balling в вашей статье тоже пароль лучше поменять
Исходные коды оригинальной Xbox утекли в онлайн
Реверс-инжиниринг неизвестного процессора по единственной программе
При размере строки 6:
...
(1800) 110111
(1806) 100001
(1812) 001011
(1818) 110000
(1824) 011000
(1830) 010010
(1836) 111100
(1842) 000110
(1848) 001001
(1856) 110001
...
Какая-то мешанина нулей и единиц.
При размере строки 20:
...
(1800) 11011110000100101111
(1820) 00000110000100101111
(1840) 00000110001001110001
(1860) 00000110000100101111
(1880) 00000110000100101111
(1900) 00000110000100101111
(1920) 00000110001010110011
(1940) 00000110000100101111
(1960) 00000110000100101111
(1980) 00000110000100101111
...
Уже явно какая-то регулярная структура.
Реверс-инжиниринг неизвестного процессора по единственной программе
Этот ваш хаскель (не) только для факториалов и годен
Конечно, есть. Сумма делителей мультипликативна в смысле теории чисел: если n=ab и a,b взаимно просты, то сумма делителей n равна произведению сумм делителей для a и b. Так что достаточно посчитать суммы для степеней простых и перемножить:
Получается быстрее в 2-3 раза.
Оптимизация сравнения this с нулевым указателем в gcc 6.1
Оптимизация сравнения this с нулевым указателем в gcc 6.1
В Word просто пошли по другому пути: не делать сложных манипуляций при access violation — тем более, что если AV вообще произошло, то в данных вполне может быть каша, а получить документ с кашей намного неприятнее, чем потерять последний сеанс работы — а периодически делать временную копию, пока данные гарантированно целы, при AV вылетать, а после перезапуска предлагать её восстановить.
Оптимизация сравнения this с нулевым указателем в gcc 6.1
Инструкция
xor edi,edi
в 64-битном режиме обнуляет весьrdi
, так что нет никакого «наполовину обнулённого» регистра.В проекте он, конечно, описан, но ведь документацию читают только ламеры ©
Все драйверы режима ядра для Windows 10 (1607) теперь должны быть подписаны Microsoft
EVENT_TRACE_FLAG_SYSTEMCALL
в https://msdn.microsoft.com/en-us/library/windows/desktop/aa363784(v=vs.85).aspx. «Ограниченное» значит «только адреса вызываемых функций и возвращаемые значения, без аргументов».tracelog -start -eflag 1 0x90
&& [пауза] &&tracelog -stop
&&tracefmt -tmf system.tmf LogFile.Etl
в формате[CPU]PID.TID::time event
. PID/TID, впрочем, придётся отслеживать руками по событиям Context Switch.Все драйверы режима ядра для Windows 10 (1607) теперь должны быть подписаны Microsoft
HDD посвящается: усмиряем приложение, прожорливое на дисковое время
...\Image File Execution Options\<filename>.exe\
можно создать значение"UseFilter"=dword:00000001
и произвольное количество подключей с произвольными именами, внутри подключей — значение"FilterFullPath"="C:\<полный путь к filename>.exe"
, тогда настройки будут браться из подключа сFilterFullPath
, совпавшим с полным путём (если такого не нашлось, то, как и раньше, из самогоIFEO\<filename>.exe\
).Разбор задач финала Технокубка 2016
История языков программирования: 100% «чистый» Си, без единого «плюса»
test2.c:
Валидно в C, ошибка линковки в C++. Если второй файл убрать, то валидно в C++, ошибка линковки в C (точнее, программа не соответствует стандарту, и может быть ошибка линковки в зависимости от настроения компилятора — будет с gcc -O0, не будет с gcc -O2).
На Википедии есть пример с
sizeof('x')
.Молчаливое преобразование к/из void*, как выше уже привели пример, отнюдь не ограничивается «ручным» выделением памяти.
Ну а если смотреть на новые стандарты, то они вообще по-разному развиваются: _Bool вместо bool, float _Complex, всякие