Alphaskins - Мой Софт, Мои Правила.

  • Автор темы Автор темы Sascha
  • Дата начала Дата начала

Sascha

Команда форума
Администратор
Ofline
Alphaskins - мой софт, мои правила.

Как то раз мне захотелось украсить свой софт альфаскинами, выбрал я значит самый крутой скин, скомпилировал приложение и.....

Unregistered skin has been loaded.
If you have a key for this skin, please insert it in the KeyList.
1.webp
Я был очень раздосадован данной несправедливостью! Какой то альфаскин посмел В МОЁМ софте показывать всплывающие окна! Ну а т.к. я еврей и платить 20 баксов за какой то скин не намерен, то решил пойти другим путём - перехватить это сообщение вообще, и в данной статье я напишу как это сделать.

Плюсы Delphi по сравнению с C# и прочими си - мы можем творить всё что угодно со своим приложением! Кстати не только со своим, вообще с любыми. Можно даже модифицировать код программы на лету всего десятком строчек! И назревает вопрос - а зачем платить если можно без труда выпилить это сообщение при старте? Раз Delphi даёт нам такие возможности, то грех не воспользоваться!

Что бы перехватить это сообщение - нам нужно поправить таблицу импорта. Если кто не знает что такое таблица импорта то поясню: в программе есть модули (DLL файлы) в которых содержатся готовые функции такие как MessageBox, что бы вызвать эту функцию программе нужно знать адрес, вот как раз таблица импорта и хранит этот адрес.
Делать это нужно до того как приложение начнёт выполнение, а значит перехватывать мы будем на точке входа:

2.webp
Не мудрствуя лукаво я погуглил и нашёл в интернете кучу информации по перехвату, но самым стабильным оказался метод с правкой таблицы импорта. Тут всё просто: мы создаём свою функцию которая будет выводить сообщения на экран (или не выводить в случае с альфаскином) и подменяем стандартную функцию нашей.

Всё, теперь мы восстановили контроль над своим приложением и сэкономили 20 баксов.

Код:
program Project1;


uses
  Windows, Forms, Unit1;

var
  OrigAddr: Pointer = nil;

{$R *.res}

function InterceptedMessageBoxA(Wnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
type
  TOrigMessageBoxA = function(Wnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
begin
  if lpCaption <> 'Unregistered skin' then
    Result := TOrigMessageBoxA(OrigAddr)(Wnd, lpText, lpCaption, uType);
end;

function Intercept(const OldProc, NewProc: FARPROC): Boolean;
var
  ImportEntry: PImageImportDescriptor;
  Thunk: PImageThunkData;
  Protect: DWORD;
  ImageBase: Cardinal;
  DOSHeader: PImageDosHeader;
  NTHeader: PImageNtHeaders;
begin
  Result := False;
  if OldProc = nil then Exit;
  if NewProc = nil then Exit;
  ImageBase := GetModuleHandle(nil);
  DOSHeader := PImageDosHeader(ImageBase);
  NTHeader := PImageNtHeaders(DWORD(DOSHeader) + DWORD(DOSHeader^._lfanew));
  ImportEntry := PImageImportDescriptor(
    DWORD(ImageBase)+
    DWORD(NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
  );
  while ImportEntry^.Name <> 0 do begin
    Thunk := PImageThunkData(DWORD(ImageBase) + DWORD(ImportEntry^.FirstThunk));
    while Pointer(Thunk^._function) <> nil do begin
      if Pointer(Thunk^._function) = OldProc then begin
        if VirtualProtect(@Thunk^._function, SizeOf(DWORD), PAGE_EXECUTE_READWRITE, Protect) then
        try
          InterlockedExchange(Integer(Thunk^._function), Integer(NewProc));
          Result := True;
        finally
          VirtualProtect(@Thunk^._function, SizeOf(DWORD), Protect, Protect);
          FlushInstructionCache(GetCurrentProcess, @Thunk^._function, SizeOf(DWORD));
        end;
      end else Inc(PAnsiChar(Thunk), SizeOf(TImageThunkData32));
    end;
    ImportEntry := Pointer(Integer(ImportEntry) + SizeOf(TImageImportDescriptor));
  end;
end;

begin
  OrigAddr:=GetProcAddress(GetModuleHandle(user32), 'MessageBoxA');
  Intercept(OrigAddr, @InterceptedMessageBoxA);

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
 
Если че у нас есть на форуме,уже крякнутые для всех версий .deal
 
Назад
Сверху Снизу