Kernel32 api

Windows hook: просто о сложном

Kernel32 api
Что такое хук? Что такое хук функций и для чего он нужен? В переводе с английского «hook» — ловушка. Поэтому о назначении хуков функции в Windows можно догадаться — это ловушка для функции. Иными словами, мы ловим функцию и берем управление на себя.

После этого определения нам открываются заманчивые перспективы: мы можем перехватить вызов любой функции, подменить код на свой, тем самым изменив поведение любой программы на то, которое нам нужно (конечно, в рамках определенных ограничений).

Целью данной статьи является демонстрация установки хука и его непосредственная реализация.

— Нельзя поверить в невозможное!
— Просто у тебя мало опыта, – заметила Королева. – В твоем возрасте я уделяла этому полчаса каждый день! В иные дни я успевала поверить в десяток невозможностей до завтрака!

Где мне реально пригодились эти знания Эти знания являются очень узкоспециализированными, и в повседневной практике разработки маловероятно, что они пригодятся, но знать о них, на мой взгляд, крайне желательно, даже если эти знания чисто теоретические. На моей практики же мне пригодились эти знания для решения следующих задач: • Контроль входящего http-траффика и подмена «взрослого» контента на более безобидный. • Логирование информации в случае копирования каких-либо файлов с подконтрольной сетевой папки. • Незначительная модификация кода в проекте, от которого были утеряны исходники (да, и такое тоже случается)

Методы установки хуков

Давайте перейдем от общих фраз к более детальному рассмотрению хуков. Мне известно несколько разновидностей реализации хука: ● Использование функции SetWindowsHookEx. Это весьма простой, оттого и ограниченный, метод. Он позволяет перехватывать только определенные функции, в основном связанные с окном (например, перехват событий, которые получает окно, щелчков мышкой, клавиатурного ввода). Достоинством этого метода является возможность установки глобальных хуков (например, сразу на все приложениях перехватывать клавиатурный ввод). ● Использование подмены адресов в разделе импорта DLL. Суть метода заключается в том, что любой модуль имеет раздел импорта, в котором перечислены все используемые в нем другие модули, а также адреса в памяти для экспортируемых этим модулем функций. Нужно подменить адрес в этом модуле на свой и управление будет передано по указанному адресу.

● Использование ключа реестра HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls. В нем необходимо прописать путь к DLL, но сделать это могут только пользователи с правами администратора. Этот метод хорош, если приложение не использует kernel32.dll (нельзя вызвать функцию LoadLibrary).

● Использование инъектирования DLL в процесс. На мой взгляд, это самый гибкий и самый показательный способ. Его-то мы и рассмотрим более подробно.

Метод инъектирования

Инъектирование возможно, потому что функция ThreadStart, которая передается функции CreateThread, имеет схожую сигнатуру с функцией LoadLibrary (да и вообще структура dll и исполняемого файла очень схожи). Это позволяет указать метод LoadLibrary в качестве аргумента при создании потока. Алгоритм инъектирования DLL выглядит так: 1. Находим адрес функции LoadLibrary из Kernel32.dll для потока, куда мы хотим инжектировать DLL. 2. Выделяем память для записи аргументов этой функции. 3. Создаем поток и в качестве ThreadStart функции указываем LoadLibrary и ее аргумент. 4. Поток идет на исполнение, загружает библиотеку и завершается. 5. Наша библиотека инъектирована в адресное пространство постороннего потока. При этом при загрузке DLL будет вызван метод DllMain с флагом PROCESS_ATTACH. Это как раз то место, где можно установить хуки на нужные функции. Далее рассмотрим саму установку хука.

Установка хука

Подход, используемый при установке хука, можно разбить на следующие составные части: 1. Находим адрес функции, вызов которой мы хотим перехватывать (например, MessageBox в user32.dll). 2. Сохраняем несколько первых байтов этой функции в другом участке памяти. 3. На их место вставим машинную команду JUMP для перехода по адресу подставной функции. Естественно, сигнатура функции должна быть такой же, как и исходной, т. е. все параметры, возвращаемое значение и правила вызова должны совпадать. 4. Теперь, когда поток вызовет перехватываемую функцию, команда JUMP перенаправит его к нашей функции. На этом этапе мы можем выполнить любой нужный код. Далее можно снять ловушку, вернув первые байты из п.2 на место. Итак, теперь нам понятно, как внедрить нужную нам DLL в адресное пространство потока и каким образом установить хук на функцию. Теперь попробуем совместить эти подходы на практике.

Тестовое приложение

Наше тестовое приложение будет довольно простым и написано на С#. Оно будет содержать в себе кнопку для показа MessageBox. Для примера, установим хук именно на эту функцию. Код тестового приложения: public partial class MainForm : Form{[DllImport(“user32.dll”, CharSet = CharSet.Unicode)]public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); public MainForm(){InitializeComponent(); this.Text = “ProcessID: ” + Process.GetCurrentProcess().Id;} private void btnShowMessage_Click(Object sender, EventArgs e){MessageBox(new IntPtr(0), “Hello World!”, “Hello Dialog”, 0);}}
Инъектор В качестве инъектора рассмотрим два варианта. Инъекторы, написанные на С++ и С#. Почему на двух языках? Дело в том, что многие считают, что С# — это язык, в котором нельзя использовать системные вещи, — это миф, можно :). Итак, код инъектора на С++: #include “stdafx.h”#include #include #include int Wait(); int main(){ // Пусть до библиотеки, которую хотим инъектировать. DWORD processId = 55; char* dllName = “C:\\_projects\\CustomHook\\Hooking\\Debug\\HookDll.dll”; // Запрашиваем PID процесса куда хотим инъектировать. printf(“Enter PID to inject dll: “); std::cin >> processId; // Получаем доступ к процессу. HANDLE openedProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (openedProcess == NULL) { printf(“OpenProcess error code: %d\r”, GetLastError()); return Wait(); } // Ищем kernel32.dll HMODULE kernelModule = GetModuleHandleW(L”kernel32.dll”); if (kernelModule == NULL) { printf(“GetModuleHandleW error code: %d\r”, GetLastError()); return Wait(); } // Ищем LoadLibrary (Суффикс A означает что работаем в ANSI, один байт на символ) LPVOID loadLibraryAddr = GetProcAddress(kernelModule, “LoadLibraryA”); if (loadLibraryAddr == NULL) { printf(“GetProcAddress error code: %d\r”, GetLastError()); return Wait(); } // Выделяем память под аргумент LoadLibrary, а именно – строку с адресом инъектируемой DLL LPVOID argLoadLibrary = (LPVOID)VirtualAllocEx(openedProcess, NULL, strlen(dllName), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (argLoadLibrary == NULL) { printf(“VirtualAllocEx error code: %d\r”, GetLastError()); return Wait(); } // Пишем байты по указанному адресу. int countWrited = WriteProcessMemory(openedProcess, argLoadLibrary, dllName, strlen(dllName), NULL); if (countWrited == NULL) { printf(“WriteProcessMemory error code: %d\r”, GetLastError()); return Wait(); } // Создаем поток, передаем адрес LoadLibrary и адрес ее аргумента HANDLE threadID = CreateRemoteThread(openedProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddr, argLoadLibrary, NULL, NULL); if (threadID == NULL) { printf(“CreateRemoteThread error code: %d\r”, GetLastError()); return Wait(); } else { printf(“Dll injected!”); } // Закрываем поток. CloseHandle(openedProcess); return 0;} int Wait(){ char a; printf(“Press any key to exit”); std::cin >> a; return 0;} Теперь тоже самое, но только на С#. Оцените, насколько код более компактен, нет буйства типов (HANDLE, LPVOID, HMODULE, DWORD, которые, по сути, означают одно и тоже). public class Exporter{[DllImport(“kernel32.dll”, SetLastError = true)]public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId); [DllImport(“kernel32.dll”, SetLastError = true)]public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport(“kernel32.dll”, CharSet = CharSet.Ansi, SetLastError = true)]public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport(“kernel32.dll”, SetLastError = true)]public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect); [DllImport(“kernel32.dll”, SetLastError = true)]public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out IntPtr lpNumberOytesWritten); [DllImport(“kernel32.dll”, SetLastError = true)]public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId); [DllImport(“kernel32.dll”, SetLastError = true)]public static extern Int32 CloseHandle(IntPtr hObject);} public class Injector{public static void Inject(Int32 pid, String dllPath){IntPtr openedProcess = Exporter.OpenProcess(ProcessAccessFlags.All, false, pid);IntPtr kernelModule = Exporter.GetModuleHandle(“kernel32.dll”);IntPtr loadLibratyAddr = Exporter.GetProcAddress(kernelModule, “LoadLibraryA”); Int32 len = dllPath.Length;IntPtr lenPtr = new IntPtr(len);UIntPtr uLenPtr = new UIntPtr((uint)len); IntPtr argLoadLibrary = Exporter.VirtualAllocEx(openedProcess, IntPtr.Zero, lenPtr, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite); IntPtr writedBytesCount; Boolean writed = Exporter.WriteProcessMemory(openedProcess, argLoadLibrary, System.Text.Encoding.ASCII.GetBytes(dllPath), uLenPtr, out writedBytesCount); IntPtr threadIdOut;IntPtr threadId = Exporter.CreateRemoteThread(openedProcess, IntPtr.Zero, 0, loadLibratyAddr, argLoadLibrary, 0, out threadIdOut); Exporter.CloseHandle(threadId);}}
Инъектируемая библиотека Теперь самое интересное — код библиотеки, которая устанавливает хуки. Эта библиотека написана на С++, пока без аналога на C#. // dllmain.cpp : Defines the entry point for the DLL application.#include “stdafx.h”#include #define SIZE 6 // Объявления функций и кастомных типовtypedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT); void BeginRedirect(LPVOID); pMessageBoxW pOrigMBAddress = NULL;BYTE oldBytes[SIZE] = { 0 };BYTE JMP[SIZE] = { 0 };DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE; BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // Уведомим пользователя что мы подключились к процессу. MessageBoxW(NULL, L”I hook MessageBox!”, L”Hello”, MB_OK); // Идем адрес MessageBox pOrigMBAddress = (pMessageBoxW)GetProcAddress(GetModuleHandleW(L”user32.dll”), “MessageBoxW”); if (pOrigMBAddress != NULL) { BeginRedirect(MyMessageBoxW); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE;} void BeginRedirect(LPVOID newFunction){ // Массив-маска для записи команды перехода BYTE tempJMP[SIZE] = { 0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3 }; memcpy(JMP, tempJMP, SIZE); // Вычисляем смещение относительно оригинальной функции DWORD JMPSize = ((DWORD)newFunction – (DWORD)pOrigMBAddress – 5); // Получаем доступ к памяти VirtualProtect((LPVOID)pOrigMBAddress, SIZE, PAGE_EXECUTE_READWRITE, &oldProtect); // Запоминаем старые байты memcpy(oldBytes, pOrigMBAddress, SIZE); // Пишем 4байта смещения. Да, код рассчитан только на x86 memcpy(&JMP[1], &JMPSize, 4); // Записываем вместо оригинальных memcpy(pOrigMBAddress, JMP, SIZE); // Восстанавливаем старые права доступа VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);} int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType){ // Получаем доступ к памяти VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL); // Возвращаем старые байты (иначе будет переполнение стека) memcpy(pOrigMBAddress, oldBytes, SIZE); // Зовем оригинальную функцию, но подменяем заголовок int retValue = MessageBoxW(hWnd, lpText, L”Hooked”, uiType); // Снова ставим хук memcpy(pOrigMBAddress, JMP, SIZE); // Восстанавливаем старые права доступа VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL); return retValue;} Ну и несколько картинок напоследок. До установки хука: И после установки: В следующем нашей материале мы постараемся написать код библиотеки, которая устанавливает хуки на C#, т. к. механизм инъектирования управляемого кода заслуживает отдельной статьи.

Авторы статьи: nikitam, ThoughtsAboutProgramming

Источник: https://habr.com/ru/company/icl_services/blog/324718/

Использование библиотек кода в windows-формах

Kernel32 api

При включении компьютера и загрузке операционной системы раздается сигнал из динамика на системном блоке. Режим залипания клавиш, включаемый при пятикратном нажатии клавиши Shift, также сопровождается звуковым сигналом.

Этот простейший динамик не может воспроизводить сложные звуки, но его иногда можно использовать, когда необходимо обратить внимание пользователя на какое-либо событие, не будучи уверенным в том, что на его компьютере имеются звуковые колонки.

Создайте новое Windows-приложение и назовите его EasySound. Располагаем на форме семь кнопок и устанавливаем следующие свойства формы и кнопок:

Form1, форма, свойствоЗначение
Size344; 264
TextEasy Sound
Button1, свойствоЗначение
NamebtnDo
Location0; 0
Size48; 232
TextДо
Button2, свойствоЗначение
NamebtnRe
Location48; 0
Size48; 232
TextРе
Button3, свойствоЗначение
NamebtnMi
Location96; 0
Size48; 232
TextМи
Button4, свойствоЗначение
NamebtnFa
Location144; 0
Size48; 232
TextФа
Button5, свойствоЗначение
NamebtnSol
Location192; 0
Size48; 232
TextСоль
Button6, свойствоЗначение
NamebtnLya
Location240; 0
Size48; 232
TextЛя
Button7, свойствоЗначение
NamebtnС
Location288; 0
Size48; 232
TextСи

Добавляем класс WinAPIClass:

using System;using System.Runtime.InteropServices;namespace EasySound{ public class WinAPIClass { #region Вызов сигнала /// /// Вызов сигнала. /// /// Частота сигнала в герцах. Диапазон от 37 до 32767 Гц. /// Продолжительность сигнала в миллисекундах. /// [DllImport(“Kernel32.dll”)] public static extern bool Beep (int frequency, int duration); #endregion }} Листинг 5.4.

Создаем обработчики для кнопок:

private void btnDo_Click(object sender, System.EventArgs e) {//В скобках: первый параметр — частота, второй — продолжительность сигнала WinAPIClass.Beep(1000, 100); } private void btnRe_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(3000, 100); } private void btnMi_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(5000, 100); } private void btnFa_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(7000, 100); } private void btnSol_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(9000, 100); } private void btnLya_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(11000, 100); } private void btnC_Click(object sender, System.EventArgs e) { WinAPIClass.Beep(13000, 100); } Листинг 5.5.

Запускаем приложение. Я не уверен, что в музыкальном смысле создаваемые сигналы в точности идентичны своим названиям, но тем не менее определенное сходство наверняка есть (рис. 5.3).

Рис. 5.3. Приложение Easy Sound

На языке С метод в обработчике будет выглядеть следующим образом:

BOOL Beep(DWORD dwFreq, DWORD dwDuration);

На диске, прилагаемом к книге, вы найдете приложение EasySound (Code\Glava5\EasySound).

Обычная Windows-форма тоже может быть анимирована, что иногда используется для создания заставки автозагрузочных дисков (рис. 5.4). К сожалению, возможное отсутствие библиотеки .

NET Framework на компьютере пользователя делает ненадежным использование такого рода приложений, написанных на C#.

Остается надеяться, что выход новой версии – Microsoft Windows Longhorn — изменит ситуацию в лучшую сторону (подробнее о распространении приложений — в “Создание пакетов установки” ).

Создайте новое приложение и назовите его AnimatedWindow. Расположите на форме три кнопки и установите следующие свойства формы и кнопок:

Form1, форма, свойствоЗначение
TextАнимация формы
Button1, свойствоЗначение
NamebtnAW_BLEND
Location30; 62
Size232; 23
TextПроявление
Button2, свойствоЗначение
NamebtnHOR_AW_SLIDE
Location30; 118
Size232; 23
TextГоризонтальное появление
Button3, свойствоЗначение
NamebtnCenter_AW_SLIDE
Location30; 182
Size232; 23
TextПоявление из центра

Добавляем класс WinAPIClass:

using System;using System.Runtime.InteropServices;using System.Windows.Forms;namespace AnimatedWindow{ public class WinAPIClass { #region Анимация окна /// /// Тип анимации окна. Перечисление возвращает тип данных int /// после приведения. Каждому элементу перечисления присвоено /// свое значение типа int. /// [Flags] public enum AnimateWindowFlags:int { AW_HOR_POSITIVE = 1, AW_HOR_NEGATIVE = 2, AW_VER_POSITIVE = 4, AW_VER_NEGATIVE = 8, AW_CENTER = 16, AW_HIDE = 65536, AW_ACTIVATE = 131072, AW_SLIDE = 262144, AW_BLEND = 524288 }; /// /// Анимация окна. /// /// Окно. /// Время. /// Тип анимации. Если в неуправляемом /// коде используется перечисление, то его нужно конвертировать /// в тип данных int. /// [DllImportAttribute(“user32.dll”,EntryPoint=”AnimateWindow”,SetLastError=true)] public static extern bool AnimateWindow(IntPtr hwnd,int dwTime,int dwFlags); /// /// Анимация окна. /// /// Окно. /// Время. /// Флаги. /// public static bool AnimateWindow(Control ctrl,int dwTime, AnimateWindowFlags Flags) { return AnimateWindow(ctrl.Handle,dwTime,(int)Flags); } #endregion }} Листинг 5.6.

Создаем обработчики кнопок:

private void btnAW_BLEND_Click(object sender, System.EventArgs e) { // Скрываем окно this.Hide(); // Запускаем анимацию. Второй параметр в скобках — время анимации в миллисекундах. WinAPIClass.AnimateWindow(this, 3000, WinAPIClass.AnimateWindowFlags.AW_ACTIVATE|WinAPIClass.AnimateWindowFlags.AW_BLEND); // Отображаем кнопки после анимации this.btnAW_BLEND.Invalidate(); this.btnHOR_AW_SLIDE.Invalidate(); this.btnCenter_AW_SLIDE.Invalidate(); } private void btnHOR_AW_SLIDE_Click(object sender, System.EventArgs e) { this.Hide(); WinAPIClass.AnimateWindow(this, 3000, WinAPIClass.AnimateWindowFlags.AW_HOR_POSITIVE|WinAPIClass.AnimateWindowFlags.AW_SLIDE); this.btnAW_BLEND.Invalidate(); this.btnHOR_AW_SLIDE.Invalidate(); this.btnCenter_AW_SLIDE.Invalidate(); } private void btnCenter_AW_SLIDE_Click(object sender, System.EventArgs e) { this.Hide(); WinAPIClass.AnimateWindow(this, 3000, WinAPIClass.AnimateWindowFlags.AW_CENTER|WinAPIClass.AnimateWindowFlags.AW_SLIDE); this.btnAW_BLEND.Invalidate(); this.btnHOR_AW_SLIDE.Invalidate(); this.btnCenter_AW_SLIDE.Invalidate(); } Листинг 5.7.

При запуске приложения доступны три вида анимации (рис. 5.5). Добавьте кнопок на форму и попробуйте вызвать другие эффекты перечисления AnimateWindowFlags.

увеличить изображение
Рис. 5.5. Анимация формы. А — готовое приложение, Б — проявление (изменение прозрачности), В — горизонтальное появление справа, Г — появление из центра (расширение)

На языке С метод в обработчике будет выглядеть следующим образом:

BOOL AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags);

На диске, прилагаемом к книге, вы найдете приложение AnimatedWindow (Code\Glava5\ AnimatedWindow).

Источник: https://intuit.ru/studies/courses/106/106/lecture/28458?page=3

Исправить ошибку KERNEL32.dll, когда библиотека не найдена

Kernel32 api

KERNEL32.dll – Это файл динамической компоновки и служит для связи с центральной частью операционной системы. Библиотека Kernel32.

dll обрабатывает управление памятью, работает с операциями ввода/вывода, синхронизацией и прерываниями. Также, предоставляет многим приложениям доступ к API-интерфейсу на основе Win32.

По этой причине, если файл поврежден каким-либо образом, то будут различные ошибки указывающие на отсутствие файла kernel32.dll

В редких случаях, может быть конфликт между программой, когда она пытается получить доступ к защищенной памяти, которая уже занята файлом Kernel32.dll. Также, многие разработчики ПО не поддерживают старые версии систем как Windows XP или Windows 7 и это распространенная ошибка у пользователей, которые пытаются запустить последние версии программ на старых ОС.

Как исправить ошибку kernel32.dll в Windows?

Ошибки Kernel32.dll могут появляться при включении компьютера, открытии или закрытии программ, и звучать по разному:

  • Не найден kernel32.dll
  • Точка входа в процедуру в библиотеке kernel32.dll не найдена
  • Commgr32 вызвал ошибку неверной страницы в модуле Kernel32.dll
  • Программа вызвала сбой в модуле Kernel32.dll
  • Точка входа в процедуру SetDefaultDllDirectories не найдены в библиотеке DLL KERNEL32.dll
  • Не удалось получить адрес процесса для GetLogicalProcessorInformation

1. Перезагрузить ПК

Если библиотека застряла в памяти и запуск программы выдаёт ошибку, то перезагрузка компьютера может решить проблему. Также, завершаться все ненужные процессы, которые могут мешать работе программы по API.

2. Переустановите программу

Программы могут устанавливаться некорректно, особенно, если вы их скачивали с торрентов и сторонних источников. Зайдите на официальный сайт производителя приложения и загрузите последнюю версию для дальнейшей установки на компьютер.

Если вы используете Windows 7 или Windows XP, то скорее всего разработчик ПО прекратил поддержку старых операционных систем. В этом случае, вам нужно скачать старую версию программы или поискать альтернативу ПО.

Также, если вы получаете ошибку с указанием на SetDefaultDllDirectories при использовании Windows 7,  Server 2008 R2 или Vista, то стоит установить патч KB2533623 для этих систем с сайта Microsoft.

3. Обновление Windows 10

Через обновления устанавливаются библиотеки для системы, DirectX и различные исправления. Многие пользователи отключают обновления Windows 10 или игнорируют их на долгий промежуток времени. Если это так, то перейдите в центр обновления Windows и установите все обновления.

4. CHKDSK, SFC и DISM

Проверим диск и системные файлы на ошибки, и если они имеются, то система попытается автоматически восстановить все повреждения. Для этого, запустите командную строку от имени администратора и введите три команды по очереди, нажимая Enter после каждой.

  1. chkdsk c: /f /r /x
  2. sfc /scannow
  3. DISM /ONLINE /CLEANUP-IMAGE /RESTOREHEALTH

5. Заменить и перерегистрировать DLL

Если есть второй рабочий компьютер или ноутбук с Windows 10, то можно взять оттуда взять отсутствующий DLL-файл и скопировать его к себе. Просто откройте проводник на втором ПК, выделите или откройте диск “C” и сверху справа в поиске вбейте название dll-файла. Если он будет найден, то нажмите по нему правой кнопкой мыши и выберите “Расположение файла”.

Также, в некоторых случаях нужно заново перерегистрировать DLL файл kernel32. Это касается и тогда, когда вы скопировали его к себе с другого компьютера. Для этого запустите командную строку от имени администратора и введите:

  • regsvr32.exe kernel32.dll

Примечание: Если столкнетесь с ошибками при регистрации, то введите команду следующего вида regsvr32 C:\Windows\System32\kernel32.dll, где нужно указать путь к файлу.

6. Файлы Thumbs.db

Иногда ошибка Kernel32.dll появляется при повреждении файлов Thumbs.db (кэш миниатюр) в папках, если к ним осуществляется доступ-запрос связанный с каким-либо DLL файлов. Нужно найти по вашему мнению папку в которой имеется поврежденный файл Thumbs.db и удалить его.

  • Это руководство поможет вам понять, что за файл Thumbs.db и как его удалить.

7. Сканирование на вирусы

Вирусы в систем Windows могут создавать различные проблемы, в том числе и с файлов Kernel32.dll. Воспользуйтесь именно антивирусным сканером как DrWeb или Zemana, чтобы проверит систему на вредоносное ПО. Вы также можете запустить встроенный антивирус “Защитник Windows” в автономном режиме.

8. Диагностика памяти

Нажмите Win+R и введите mdsched.exe, чтобы запустить диагностику памяти. Если диагностика памяти выявит ошибки и не исправит их, то можете обратиться к подробному руководству.

9. Обновить драйвера

Если ошибка Kernel32.dll появляется при печати принтера, то нужно обновить драйвер принтера до последней версии. Если она появляется при запуске игр, то драйвер видеокарты.

Загрузка комментариев

Источник: https://mywebpc.ru/windows/fix-error-kernel32-dll/

Некоторые функции Win32

Kernel32 api
Руслан Аблязов
6 октября 2006 года

На прошлом уроке мы написали первое оконное приложение на ассемблере. На прошлом уроке я вам рассказал структуру ЛЮБОГО оконного приложения. Сегодня я вам расскажу (т.е. опишу) несколько функций API для работы с памятью.

Как я вам уже рассказывал, в Win32 есть только API функции. ЛЮБОЕ приложение в ЛЮБОМ случае должно использовать АПИ функции (по крайней мере, для того чтобы оно могло нормально завершиться). Эти функции находятся в библиотеках kernel32.dll, user32.dll, gdi32.dll (3 классические библиотеки) и др.

Функции библиотеки kernel32.dll самые главные, они отвечают за работу с файлами памятью, от них никуда не денешься, user32.dll отвечает за окна и интерфейс пользователя, а gdi32.dll за “рисование” и мультимедиа. Для того, что бы использовать функции этих библиотек надо сначала их загрузить (kernel32.

dll загружать не надо).

Каждое приложение проецируется в своё собственное виртуальное адресное пространство размером в 4 ГБ, верхние 2 из которых недоступны для него. Это пространство (вернее нижние 2 ГБ) подготавливается для него: в него загружаются 2 библиотеки kernel32.dll и ntdll.

dll (для Win NT) всегда по одинаковым адресам, подготавливается стек для главной нити процесса и ещё много чего. В эту память загружаются код и данные приложения. Для того, что бы операционная система знала по каким адресам надо загружать данные и код приложения она смотрит дополнительную информацию о секциях приложения в “экзе” файле.

Если она этого не сделает, то она просто не будет знать, куда спроецировать код и данные, следовательно, все обращения к памяти будут неверными.

(Мы, конечно, помним что под записью mov eax, [value] понимается помещение в регистр eax содержимого некого адреса памяти, которую подразумевает метка value, эта метка подразумевает некий фиксированный адрес, все адреса рассчитываются при компиляции программы и вам об этом задумываться не надо).

Каждое приложение в своей работе вызывает API функции, под вызовом функции подразумевается передача управления некоторому адресу, который находится в диапазоне памяти, в которую загружена библиотека, которая содержит данную функцию. Рассмотрим пример.

Call VirtualAalloc

Как мы уже знаем слово VirtualAlloc будет заменено на некоторый адрес. Этот адрес будет соответствовать адресу точки входа функции VirtualAlloc.

Потом эта функция передаёт управление функциям Native API которые находятся в библиотеке ntdll.dll. Функции Native API подготавливают процесс к переходу в режим ядра и командой sysenter переводят процесс в режим ядра и т.д.

Дальше я не буду рассказывать, потому что это слишком много для одного урока.

Теперь я опишу несколько API функций для работы с памятью.

Функция VirtualAlloc позволяет зарезервировать некоторый участок памяти заданного размера, при этом эта память полностью обнуляется.

Вот описание этой функции из MS SDK в оригинале

LPVOID VirtualAlloc( LPVOID lpAddress, // address of region to reserve or commit DWORD dwSize, // size of region DWORD flAllocationType, // type of allocation DWORD flProtect // type of access protection );

  • lpAddress – начальный адрес региона
  • dwSize – размер региона
  • flAllocationType – тип резервирования может быть указана одна из 3х констант :
    • MEM_COMMIT эта память может быть сброшена в файл подкачки
    • MEM_RESERVE этот участок памяти не может быть сброшен в файл подкачки он будет присутствовать в физической памяти всегда, пока эту память процесс не ввысвободит.
    • MEM_TOP_DOWN не пойму для чего нужна эта константа, но она есть, она позволяет зарезервировать виртуальную память, которая будет соответствовать максимально возможному физическому адресу.
  • flProtect тип доступа к памяти. Могут быть использованы эти константы или их комбинации.
    • PAGE_READONLY
    • PAGE_READWRITE
    • PAGE_EXECUTE позволяет передавать управление этому региону попытка чтения или записи приводит к нарушению прав доступа.
    • PAGE_EXECUTE_READ
    • PAGE_EXECUTE_READWRITE
    • PAGE_NOACCESS

Мне кажется всё и так понятно, кому не понятно читайте MS SDK.

Функция VirtualFree обратна функции VirtualAlloc высвобождает заданный диапазон памяти.

BOOL VirtualFree( LPVOID lpAddress, // начальный адрес освобождаемого региона DWORD dwSize, // размер региона DWORD dwFreeType // type of free operation );

dwFreeType метод высвобождения:

если укажете MEM_RELEASE то размер указывать не надо, если MEM_DECOMMIT, то размер надо указывать остальных различий, если указано MEM_RELEASE, то эта память высвобождается полностью.

Если функция завершилась нормально, то результат отличен от нуля.

Функция VirtualProtect позволяет изменить тип доступа к зарезервированной памяти, но не так всё просто надо ещё указать старый тип доступа.

BOOL VirtualProtect( LPVOID lpAddress, // начальный адрес DWORD dwSize, // размер DWORD flNewProtect, // новый тип доступа PDWORD lpflOldProtect // старый тип доступа );

Вроде всё понятно.

Функция VirtualLock блокирует участок памяти, при этом доступ к нему невозможен и одновременно не приводит к ошибке.
BOOL VirtualLock( LPVOID lpAddress, // начальный адрес DWORD dwSize // размер );

При удачном исходе результат не равен нулю.

Функция VirtualUnlock обратная предыдущей функции.

BOOL VirtualUnlock( LPVOID lpAddress, DWORD dwSize );

При удачном исходе результат не равен нулю.

Все указанные выше функции могут работать только с памятью текущего процесса.

На сегодня хватит. Для этих целей существует MS SDK. Я объяснил только несколько функций. Вот и конец 15 урока моего туториала.

Назад |Оглавление |Далее

Источник: http://www.codenet.ru/progr/asm/newbee/lesson15.php

Поделиться:
Нет комментариев

    Добавить комментарий

    Ваш e-mail не будет опубликован. Все поля обязательны для заполнения.