Защита программ

Раздел посвящен программированию с использованием Power Basic.
Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Защита программ

Сообщение Dark Machine » 21.09.2007 (Пт) 13:34

Тема:
Защита программ от трассировки, отладчиков и дизассемблрования.

Предлагаю постить идеи и/или готовые решения.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 21.09.2007 (Пт) 14:30

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

Код: Выделить всё
#Compile Exe
#Include "win32api.inc"

Function PBMain() As Long
On Error Resume Next
    Dim hLib As Long, hProc As Long, lRet As Long
    Dim sFunc As Asciiz * %MAX_PATH
      sFunc = "IsDebuggerPresent"
      hLib = LoadLibrary("kernel32.dll")
      hProc = GetProcAddress(hLib, sFunc)
    ! call hProc
    ! mov lRet, eax
    If lRet = 1 Then
        MsgBox "Включен отладчик!"
    Else
        MsgBox "Отладчик не обнаружен"
    End If
End Function



Ну, кто будет следующим?

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 21.09.2007 (Пт) 15:40

В догонку еще один способ обнаружения отладчиков. Запросто ловит OllyDbg и т.п. И в отличие от первого примера, работает под 9x и NT5


Код: Выделить всё
#Compile Exe
#Dim All
#Include "win32api.inc"
   
Function IsDebuggerAttached() As Long
         Local vi As OSVERSIONINFO
         Local IsWin9x As Long
         Local Dw As Dword
         Local i  As Dword
  vi.dwOsVersionInfoSize = SizeOf(vi)
  GetVersionEx vi
  IsWin9x =  ((vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS) And (vi.dwMinorVersion =  0)) Or _
             ((vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS) And (vi.dwMinorVersion <> 0))
  If IsWin9x Then
        !push eax                        '// Preserve the registers
        !mov eax, fs:[&h18]              '// Get the TIB's linear address
        !mov eax, dword ptr [eax + &h20] '// Debugger Contex for Win9x
        !mov dword ptr dw,  eax          '// Save it
        !pop eax                         '// Restore the registers
        If Dw Then
           Function = -1
        Else
           Function = 0
        End If
   Else
        !push eax                        '// Preserve the registers
        !push ecx
        !mov eax, fs:[&h18]              '// Get the TIB's linear address
        !mov eax, dword ptr [eax + &h30]
        !mov ecx, dword ptr [eax]        '// Get the whole DWORD
        !mov dword ptr dw,  ecx          '// Save it
        !pop ecx                         '// Restore the registers
        !pop eax
       i= dw And &h00010000???
       If i Then
          Function = -1
       Else
          Function = 0
       End If
   End If
End Function

Function PBMain () As Long
  If IsDebuggerAttached=-1 Then
        MsgBox "Работаем под отладчиком!"
   Else
        MsgBox "Отладчик не обнаружен"
  End If
End Function
                             

PBDN
Обычный пользователь
Обычный пользователь
 
Сообщения: 59
Зарегистрирован: 21.10.2006 (Сб) 22:10

Сообщение PBDN » 21.09.2007 (Пт) 17:30

Пример обнаружения отладчика через API функцию IsDebuggerPresent, любой средний кракер легко пропатчит такую программу.


а)
Если в лоб оставлять в екзешнике IsDebuggerPresent строку, тогда конечно :) Но если закриптовать через CryptoAPI жизненно важные строки, то она уже не будет так хорошо видима, к тому же еще есть способ вызова через ординал, где текста вообще не будет видно. Хотя если хакер видит в таблице импорта крипто АПИ, у него уже пропадают на 50% желание вообще возиться.

б)
Можно запустить ленивый поток который будет считывать счетчик ЦПУ
через опкод RDTSC и если разница между считываниями значительно больше установленного порога, то работает дебаггер

б)
начиная от hInstance и до конца имиджа чекать ЦРЦ, если что то поменяно, то показывать балалайку

в)
Важные участки кода можно также закриптовать, и распаковывать в динамике на лету, приводя просчет ЦРЦ распаковки всегда к нулю, тем самым не делая явного сравнивания ИФ црц = правильному црц а оставляя кучу ложных просчетов тоже приводящих к нулю .

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

д)
вообще на тему запутывания на ПБ форуме есть неплохие идейки,
например :
http://www.powerbasic.com/support/pbfor ... +the+stack
http://www.powerbasic.com/support/forum ... 01536.html

е)
полезные ссылки:

http://bbs.pediy.com/archive/index.php?t-29825.html

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 24.09.2007 (Пн) 8:35

А как насчет защиты от сдампливания? Порча секций импорта, заголовка PE? Есть идеи?

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 24.09.2007 (Пн) 15:46

Есть. Дампер никогда не задампит kernel-mode хэндлы. Мораль - завяжи работы на них.
Изображение

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 24.09.2007 (Пн) 16:05

keks-n писал(а):Есть. Дампер никогда не задампит kernel-mode хэндлы. Мораль - завяжи работы на них.


Что-то не пойму. В kernel-mode работают только NT-драйвера и ядро ОС. Каким образом user-mode программа может использовать для защиты хендлы от туда?

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 27.09.2007 (Чт) 9:52

Вот еще пример, защита от распаковки, путем патча собственной кодовой секции. Упакованная программа нормально работает, неупакованная сваливается с GPF


Код: Выделить всё
#Compile Exe
#Include "win32api.inc"

Global imgSection() As IMAGE_SECTION_HEADER

Function AppExeName() As String
On Error Resume Next
  Local buffer  As Asciiz * 256
  GetModuleFileName GetModuleHandle(ByVal 0&), Buffer, 256
  Function = Buffer
End Function

Function FileOffset(RVA As Dword) As Dword
'Convert relative virtual address to file offset
Dim I As Dword, LastEntry As Dword
LastEntry = UBound(imgSection) - 1
For I = 0 To LastEntry
  If RVA >= imgSection(i).VirtualAddress Then
     If I = LastEntry Then
         FoundOffset:
         Function = RVA - imgSection(i).VirtualAddress + imgSection(i).PointerToRawData
     Else
        If RVA < imgSection(i + 1).VirtualAddress Then GoTo FoundOffset
     End If
  End If
Next I
End Function

Function PBMain() As Long
   Local ExeHdrInfo As IMAGE_NT_HEADERS
   Local DOSHdr As Image_DOS_Header
   Local I As Long, RVA As Dword
   Open AppExeName For Binary Access Read Lock Shared As #1
   Get #1,, DosHdr
   Seek #1, 0
   Seek #1, DosHdr.e_lfanew + 1
   se% = Seek(#1)
   Get #1,, ExeHdrInfo
   ReDim imgSection(ExeHdrInfo.FileHeader.NumberOfSections) As IMAGE_SECTION_HEADER
   For I = 0 To ExeHdrInfo.FileHeader.NumberOfSections - 1
    Get #1, 25 + DosHdr.e_lfanew + ExeHdrInfo.FileHeader.SizeOfOptionalHeader + (40 * I), imgSection(i)
   Next I
   Close #1
   RVA = ExeHdrInfo.OptionalHeader.AddressOfEntryPoint   'the relative virtual address we want to convert
   RVA = RVA + ExeHdrInfo.OptionalHeader.ImageBase
   Poke RVA, &hC3  'C3 = ret
   MsgBox "Hello world!"
End Function

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 27.09.2007 (Чт) 10:34

jangle
Всё просто. У тебя должен быть описатель некого объекта(пайпа там, файла), который легко получается из user-mode. Тем не менее, реально объект существует в ядре. Если есть к ним какая-то привязка в рантайме, то после запуска отдампленого файла она работать не будет, т. к. хэндл указывает в никуда.
+Можно сделать совсем идиотским образом - перехватить некоторые API и изменить их поведение(программа должна ориентироваться на новое), тогда после загрузки отдаменного образа изменений в системных DLL не будет, и поведение будет стандартным.
Изображение

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 26.11.2007 (Пн) 23:07

Вместо
Код: Выделить всё
! jmp  ret1

Использовать

Код: Выделить всё
! push ret1
! retn


Пример использования от Steve Hutchesson
Код: Выделить всё
#COMPILE EXE
#INCLUDE "WIN32API.INC"

FUNCTION PBmain as LONG

      LOCAL ret1 as LONG
      LOCAL ret2 as LONG
      LOCAL ret3 as LONG
 
      ret3 = CodePtr(nextLabel)
      ret2 = CodePtr(do_that)
      ret1 = CodePtr(do_this)
 
      ! push ret3
      ! push ret2
      ! jmp  ret1
 
      NextLabel:
      MsgBox "Hi, I am back"
 
      FUNCTION = 0
 
  End FUNCTION
 
  SUB do_this
      MsgBox "I am at 'do_this' sub"
  END SUB

  SUB do_that
      MsgBox "I am at 'do_that' sub"
  END SUB

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 27.11.2007 (Вт) 10:08

И как это поможет противодействовать кракерам?

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 27.11.2007 (Вт) 12:57

замена безусловного перехода, а также замена непосредственного вызова подпрограмм. т.е. вместо call у тебя push и jmp

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 27.11.2007 (Вт) 13:47

чего-то я не догоняю, разве под отладчиком этого не видно? В чем смысл такой защиты?

SLUTER
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.06.2010 (Вс) 18:26

Re: Защита программ

Сообщение SLUTER » 27.04.2011 (Ср) 19:29

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

Криптор
Код: Выделить всё
$COMPILE EXE "CRYPT.EXE"

FUNCTION PBMAIN() AS LONG
    DIM L1 AS DWORD
    DIM L2 AS DWORD
    DIM L3 AS DWORD
    DIM A1 AS STRING
    DIM I AS LONG
    DIM V AS STRING

    OPEN "TEST.EXE" FOR BINARY AS #1
        L1 = LOF(1)
        GET$ #1, L1, A1
        V = CHR$(255) & CHR$(255) & CHR$(0) & CHR$(1) & CHR$(255) & CHR$(255)
        L1 = INSTR(A1, V) + 6
        L2 = INSTR(L1, A1, V)
        L3 = L2 - L1
        FOR I = 0 TO L3 - 1
            MID$(A1, L1 + I, 1) = CHR$(ASC(MID$(A1, L1 + I, 1)) XOR ASC("T"))
        NEXT I
        SEEK #1, 1
        PUT$ #1, A1
    CLOSE #1
    EXIT FUNCTION
END FUNCTION 



Тестовая прога
Код: Выделить всё
$COMPILE EXE "TEST.EXE"

DECLARE FUNCTION VirtualProtectC LIB "KERNEL32.DLL" ALIAS "VirtualProtect" (BYVAL lpAddress AS DWORD, BYVAL dwSize AS DWORD, BYVAL flNewProtect AS DWORD, BYREF lpflOldProtect AS DWORD) AS DWORD
DECLARE FUNCTION FlushInstructionCacheC LIB "KERNEL32.DLL" ALIAS "FlushInstructionCache" (BYVAL hProcess AS DWORD, BYVAL lpBaseAddress AS DWORD, BYVAL dwSize AS DWORD) AS DWORD
DECLARE FUNCTION GetCurrentProcessC LIB "KERNEL32.DLL" ALIAS "GetCurrentProcess" () AS DWORD

%PAGE_READWRITE = 4&


SUB DecryptCode(L1 AS LONG, L2 AS LONG)
    DIM A1 AS STRING
    DIM L3 AS DWORD
    DIM Mode AS DWORD
    DIM Result AS LONG
    DIM OrigMode AS DWORD
    DIM I AS LONG
    DIM Key AS LONG

    Key = ASC("T")

    L3 = L2 - L1
    A1 = PEEK$(L1, L3)

    FOR I = 1 TO L3
        MID$(A1, I, 1) = CHR$(ASC(MID$(A1, I, 1)) XOR Key)
    NEXT I

    MODE = %PAGE_READWRITE
    Result = VirtualProtectC(L1, L3, MODE, OrigMode)
    POKE$ L1, A1
    Result = VirtualProtectC(L1, L3, OrigMode, MODE)
    Result = FlushInstructionCacheC(GetCurrentProcessC(), L1, L3)
    EXIT SUB
END SUB

FUNCTION PBMAIN() AS LONG
    CALL DecryptCode(CODEPTR(Label1), CODEPTR(Label2))
    GOTO Label1:

    ! DB 255, 255, 0, 1, 255, 255
    Label1:

    MSGBOX "Hello"

    EXIT FUNCTION

    Label2:
    ! DB 255, 255, 0, 1, 255, 255
END FUNCTION

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Защита программ

Сообщение Хакер » 28.04.2011 (Чт) 18:40

Указанным кусочком кода — совершенно точно не стоит. Даже не потому, что он совершенно никого не остановит, а потом что он ещё и сильно неправильный.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLUTER
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.06.2010 (Вс) 18:26

Re: Защита программ

Сообщение SLUTER » 28.04.2011 (Чт) 22:56

Хакер писал(а):а потом что он ещё и сильно неправильный.

а почему неправильный?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Защита программ

Сообщение Хакер » 28.04.2011 (Чт) 23:11

Ну, на один пункт неправильность меньше. Я проглядел второй VirtualProtect.

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

Когда-то я делал схемы, в которых расшифрование происходило небольшими кусочками, которые прыгали по памяти, и где для расшифрования следующего кусочка нужен был хеш предыдущего. Но и это было очень простой защитой. А предложенная здесь — ещё на несколько порядков сложнее при своей, так сказать, инженерной нелепости.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Power Basic

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 42

    TopList