МЕНЮ

МЕНЮ  гуморески  инфо



МЕНЮ

МЕНЮ  гуморески  инфо 
Защищиаем свою программу

Защищиаем свою программу
«Конца войны дождутся только мёртвые»
Сократ

«Крякеры» или любители ломать крякми знают, что большинство защит ломаются заменой не более десятка байтов. Да, и в правду этой истины можно поверить взглянув на такой вот код(эти вырезки – части реальных программ, но названы мною они не будут):


...50 | push eaxe873000000 | call *******; хеш - функция83c408 | add esp,08h

09c0 | or eax,eax

7416 | jz ******* ; переходит на функцию вывода

; сообщения о неверных паролях(там их три)

6a00 | push 0 ; продолжается выполнение программы

...


Как нетрудно заметить, что в дампе надо заменить 74 на 75 и будет не jz, a jnz. В такой программе совсем не нужна хеш-функция. Хотя в данной программе она не совсем то тривиальна, поверьте мне, но видимо человек создающий защиту пользовался не ассемблером, а языком высокого уровня и на скорую руку, ведь криптостойкость такой системы равна нулю.

Вот ещё один пример:

; здесь hash – функция с постоянным ключом,

813ed0203534 | cmp dword [esi],0343520d0h7526 | jne **** ;переходим на код, сообщающий о неверном пароле817e04c030575e | cmp dword [esi+4],05e5730c0h751d | jne **** ;переходим на код, сообщающий о неверном пароле

817e084050bd58 | cmp dword [esi+8],058bd5040h

7514 | jne **** ;переходим на код, сообщающий о неверном пароле

... ;всё отлично? Работаем дальше.


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

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

Мораль: ни когда не делайте явных вызовов j** в своих защитных системах. Но как же быть?

Идея следующая:

пишем программу;

придумываем хеш-функцию (или несколько, о чём позже);

шифруем весь код и запоминаем ключ, который будет в дальнейшем паролём;

заносим в код эту функцию и предоставляем пользователю возможность ввести пароль.

Очевидно, что пока пользователь не имеет пароля он не получит верный код (есть шифротекст, функция, но нет ключа). А самое главное – пропатчить не удастся, и код не содержит лишней информации. Кстати, это статический метод, но есть и динамический. Он предполагает расшифровку не всего кода, а отдельных частей. Т.е. мы расшифровали первую часть, а остальные остались зашифрованными. Затем мы расшифровываем вторую часть, передаём ей управление, и зашифровываем первую часть. Имейте ввиду, что совсем не обязательно использовать, как я уже говорил, одну hash-функцию и один пароль.

Мной сделан выбор в пользу этого метода, так как никакой дизассемблер не поможет, а ведь с помощью таких вот инструментов можно расшифровать адрес того j***, как нам советуют многие.

Выбор делать Вам.

В заключение покажу вам пример. Вот полный код такой программы примера:

format PE GUI 4.0entry startinclude 'win32a.inc'ID_PASSWORD = 101

section '.data' data readable writeable

flags dd ?

caption db 'Result',0

message db 'Hello Wordld!',0

password rb 100h

section '.code' code readable writable executable

start:

invoke GetModuleHandle,0

invoke DialogBoxParam,eax,37,HWND_DESKTOP,DialogProc,0

or eax,eax

jz exit

invoke MessageBox,HWND_DESKTOP,message,caption,[flags]

exit:

invoke ExitProcess,0

proc DialogProc,hwnddlg,msg,wparam,lparam

push ebx esi edi

cmp [msg],WM_COMMAND

je wmcommand

cmp [msg],WM_CLOSE

je wmclose

xor eax,eax

jmp finish

wmcommand:

cmp [wparam],BN_CLICKED shl 16 + IDCANCEL

je wmclose

cmp [wparam],BN_CLICKED shl 16 + IDOK

jne processed

invoke GetDlgItemText,[hwnddlg],ID_PASSWORD,password,100h

mov [flags],MB_OK

;decoder

mov al,byte [password]

and al,00000001b

cmp al,0

je one

nil:

mov cl,byte [password + 2]

jmp unhash

one:

mov cl,byte [password +3]

unhash:

mov edx,0

mov eax,htext

circl:

xor byte [htext+ebx],cl

inc ebx

inc eax

cmp eax,hend

jne circl

htext: ;start hash-text

cmp dword [ebx+03bh],edx

push edi

inc ebx

adc edx,dword [ebx+03bh]

pop eax

inc ebx

adc edx,dword [ebx+039h]

push ebx

lods byte [esi]

inc esi

cli

db 063h,013h

push ebx

hend:

;end hash-text

jmp processed

wmclose:

invoke EndDialog,[hwnddlg],0

processed:

mov eax,1

finish:

pop edi esi ebx

return

endp

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',\

user,'USER32.DLL'

import kernel,\

GetModuleHandle,'GetModuleHandleA',\

ExitProcess,'ExitProcess'

import user,\

DialogBoxParam,'DialogBoxParamA',\

GetDlgItemText,'GetDlgItemTextA',\

MessageBox,'MessageBoxA',\

EndDialog,'EndDialog'

section '.rsrc' resource data readable

directory RT_DIALOG,dialogs

resource dialogs,\

37,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration

dialog demonstration,'Example to artical by X-H:01xd',160,120,190,60,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME

dialogitem 'STATIC','&Input password:',-1,10,10,70,8,WS_VISIBLE

dialogitem 'EDIT','',ID_PASSWORD,10,20,170,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL

dialogitem 'BUTTON','OK',IDOK,10,40,45,15,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON

dialogitem 'BUTTON','C&ancel',IDCANCEL,60,40,45,15,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON

enddialog


Это можно сказать крякми. При запуске exe-шника мы видим окно с просьбой ввести пароль. Вводим например пароль hacker и после нажатия кнопки «Ок» нам предлагают отправить Биллу ошибку, гарантируя конфиденциальность. Но соображающие люди решат посмотреть в исходник и что тут видят: белиберду начиная с htext до hend.

Смотрим дальше, при вводе пароля он сохраняется в password и после определения чётности первого байта выбираем ключ (это мы понимаем, анализируя дальнейший код) размером в один байт по смещению от password на 2 или 3 байта. Дальше ксорим этот ключ с белибердой и, если смотреть в трассировщике, получаем какую то белиберду.

ВСЁ! Больше мы ничего не можем определить, имея даже исходники! Да, ведь здесь нужен верный ключ, а его у нас нет. Таким образом разблокировать программу можно только узнав пароль у автора. Вот я вам говорю правильный пароль: OBST (сокращённо от offbit sec. team). Вводим его и что же мы видим – эта белиберда есть зашифрованный вызов invoke MessageBox,0,message,caption,0;

Конечно, можно сюда прикрутить ещё много и много всяких «фишек», но это уже ваша фантазия и мастерство.
На этом, пожалуй, и окончится моя статья.