• XSS.stack #1 – первый литературный журнал от юзеров форума

При патче метода происходит исключение

Bizonozubr

floppy-диск
Пользователь
Регистрация
28.02.2023
Сообщения
4
Реакции
1
Здравствуйте, дорогие форумчане!
Затупаю на одном моменте и не могу обойти проверку ключа в одной функции. Есть установщик программы (ссылка на файлообменик). Сама программа написана на Delphi, IDR отлично отрабатывает, показывает всё, что мне нужно.
В программе реализована проверка на USB HASP ключ и проверка на лицензию. Везде на клики кнопок навешана функция проверки ключа, для примера:
C:
//----- (007904D8) --------------------------------------------------------
int __fastcall TMainForm_FileSaveClick(_BYTE *a1)
{
  if ( !(unsigned __int8)((int (*)(void))loc_792AD4)() )
    TCustomForm_Close(a1);
  TMainForm_TrySaveFile((int)a1);
  TMainForm_UpdateTreeView((int)a1);
  return TMainForm_UpdateStatusbar((int)a1);
}

//----- (00790504) --------------------------------------------------------
int __fastcall TMainForm_FileSaveAsClick(_BYTE *a1)
{
  if ( !(unsigned __int8)((int (*)(void))loc_792AD4)() )
    TCustomForm_Close(a1);

  if ( (unsigned __int8)TMainForm_GetNewFileName((int)a1, (int *)off_7C4C8C) )
    TMainForm_TrySaveFile((int)a1);
  TMainForm_UpdateTreeView((int)a1);
  return TMainForm_UpdateStatusbar((int)a1);
}

Как видно уже из декомпилированного кода, если пропустить проверку, то дальше по условию код выполняется и всем хорошо.
Но при вызове двух кликов - на открытие файла и создание нового файла, вызов метода идёт с параметрами. Если его просто пропустить по JNE из-за этого приложение будет обращаться к региону памяти, к которому нет доступа и приложение падает.
C:
//----- (0078FEA4) --------------------------------------------------------
_DWORD *__fastcall TMainForm_FileNewClick(int a1)
{  if ( !(unsigned __int8)((int (__cdecl *)(struct _EXCEPTION_REGISTRATION_RECORD *, void *, int *))loc_792AD4)( v8, &unk_79007D, &savedregs) )
    TCustomForm_Close((_BYTE *)a1);
}
 
//----- (007900C4) --------------------------------------------------------
int __fastcall TMainForm_FileOpenClick(int a1)
{
  if ( !(unsigned __int8)((int (__cdecl *)(struct _EXCEPTION_REGISTRATION_RECORD *, void *))loc_792AD4)(v7, &unk_790358) )
    TCustomForm_Close((_BYTE *)a1);
}

//----- (00790A44) --------------------------------------------------------
void __fastcall TMainForm_ToolsSendClick(_BYTE *a1)
{
  _DWORD *v1; // esi
    __writefsdword(0, (unsigned int)&v6);
  if ( !(unsigned __int8)((int (__stdcall *)(struct _EXCEPTION_REGISTRATION_RECORD *, void *, int *))loc_792AD4)( v6,&unk_790B93, &savedregs) )
    TCustomForm_Close(v11);
}

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

C:
void FUN_00792ad4(void)

{
  undefined *puVar1;
  int iVar2;
  int iVar3;
  undefined4 *in_FS_OFFSET;
  undefined4 uVar4;
  undefined4 uStack_2c;
  undefined *puStack_28;
  undefined *puStack_24;
  int local_14;
  undefined local_10;
  undefined4 local_c [2];
 
  puStack_24 = &stack0xfffffffc;
  local_c[0] = 0;
  puStack_28 = &DAT_00792beb;
  uStack_2c = *in_FS_OFFSET;
  *in_FS_OFFSET = &uStack_2c;
  if (*gvar_007C4420 == '\0')
  {
    iVar3 = 0;
    puStack_24 = &stack0xfffffffc;
    do {
      iVar2 = FUN_005de4ab();
      if (iVar2 != 0)
      {
        iVar2 = FUN_005de4ab();
      }
      if (iVar2 != 0)
      {
        if (iVar2 == 7) {
          iVar3 = MessageDlg(*(undefined4 *)
                              (PTR_gvar_007C10AC_007c43e8 + (uint)(byte)*gvar_007C42C4 * 0x38 + 0x18
                              ),1,0x28,0);
        }
        else {
          uVar4 = 0;
          local_10 = 0;
          local_14 = iVar2;
          Format(*(undefined4 *)
                  (PTR_gvar_007C10AC_007c43e8 + (uint)(byte)*gvar_007C42C4 * 0x38 + 0x20),&local_14,
                 0,local_c);
          iVar3 = MessageDlg(local_c[0],1,4,uVar4);
        }
      }
    }
    while (((iVar2 != 0) && (iVar3 != 2)) && (iVar3 != 1));
    FUN_005de5bb();
  }
 
  puVar1 = puStack_24;
  *in_FS_OFFSET = uStack_2c;
  puStack_24 = &LAB_00792bf2;
  puStack_28 = (undefined *)0x792bea;
  _UStrClr(local_c,uStack_2c,puVar1);
  return;
}

Код:
//00792AC4
procedure TMainForm.SettingsLicensesClick(Sender:TObject);
begin
{*
 00792AC4    mov         eax,[007C4A04];^gvar_009037C8:TLicenseManagerForm
 00792AC9    mov         eax,dword ptr [eax]
 00792ACB    mov         edx,dword ptr [eax]
 00792ACD    call        dword ptr [edx+13C]
 00792AD3    ret
*}
end;

//00792AD4
{*function sub_00792AD4:?;
begin
 00792AD4    push        ebp
 00792AD5    mov         ebp,esp
 00792AD7    add         esp,0FFFFFFF0
 00792ADA    push        ebx
 00792ADB    push        esi
 00792ADC    push        edi
 00792ADD    xor         eax,eax
 00792ADF    mov         dword ptr [ebp-8],eax
 00792AE2    xor         eax,eax
 00792AE4    push        ebp
 00792AE5    push        792BEB
 00792AEA    push        dword ptr fs:[eax]
 00792AED    mov         dword ptr fs:[eax],esp
 00792AF0    mov         eax,[007C4420];^gvar_007CA838
 00792AF5    cmp         byte ptr [eax],0
>00792AF8    je          00792B01
 00792AFA    mov         bl,1
>00792AFC    jmp         00792BD5
 00792B01    xor         ebx,ebx
 00792B03    xor         esi,esi
 00792B05    lea         eax,[ebp-4]
 00792B08    push        eax
 00792B09    mov         eax,[007C4158];^gvar_0078AB68
 00792B0E    push        eax
 00792B0F    push        1
 00792B11    call        005DE4AB
 00792B16    mov         edi,eax
 00792B18    test        edi,edi
>00792B1A    je          00792B32
 00792B1C    lea         eax,[ebp-4]
 00792B1F    push        eax
 00792B20    mov         eax,[007C4158];^gvar_0078AB68
 00792B25    push        eax
 00792B26    push        0FFFF4800
 00792B2B    call        005DE4AB
 00792B30    mov         edi,eax
 00792B32    mov         eax,edi
 00792B34    sub         eax,1
>00792B37    jb          00792B40
 00792B39    sub         eax,6
>00792B3C    je          00792B44
>00792B3E    jmp         00792B74
 00792B40    mov         bl,1
>00792B42    jmp         00792BBA
 00792B44    push        0
 00792B46    mov         eax,[007C42C4];^gvar_007CA830
 00792B4B    movzx       eax,byte ptr [eax]
 00792B4E    imul        eax,eax,7
>00792B51    jno         00792B58
 00792B53    call        @IntOver
 00792B58    mov         edx,dword ptr ds:[7C43E8];^gvar_007C10AC
 00792B5E    mov         eax,dword ptr [edx+eax*8+18]
 00792B62    movzx       ecx,word ptr ds:[792BFC];0x28 gvar_00792BFC
 00792B69    mov         dl,1
 00792B6B    call        MessageDlg
 00792B70    mov         esi,eax
>00792B72    jmp         00792BBA
 00792B74    push        0
 00792B76    lea         eax,[ebp-8]
 00792B79    push        eax
 00792B7A    mov         eax,[007C42C4];^gvar_007CA830
 00792B7F    movzx       eax,byte ptr [eax]
 00792B82    imul        eax,eax,7
>00792B85    jno         00792B8C
 00792B87    call        @IntOver
 00792B8C    mov         edx,dword ptr ds:[7C43E8];^gvar_007C10AC
 00792B92    mov         eax,dword ptr [edx+eax*8+20]
 00792B96    mov         dword ptr [ebp-10],edi
 00792B99    mov         byte ptr [ebp-0C],0
 00792B9D    lea         edx,[ebp-10]
 00792BA0    xor         ecx,ecx
 00792BA2    call        Format
 00792BA7    mov         eax,dword ptr [ebp-8]
 00792BAA    movzx       ecx,word ptr ds:[792C00];0x4 gvar_00792C00
 00792BB1    mov         dl,1
 00792BB3    call        MessageDlg
 00792BB8    mov         esi,eax
 00792BBA    test        edi,edi
>00792BBC    je          00792BCC
 00792BBE    cmp         esi,2
>00792BC1    je          00792BCC
 00792BC3    cmp         esi,1
>00792BC6    jne         00792B05
 00792BCC    mov         eax,dword ptr [ebp-4]
 00792BCF    push        eax
 00792BD0    call        005DE5BB
 00792BD5    xor         eax,eax
 00792BD7    pop         edx
 00792BD8    pop         ecx
 00792BD9    pop         ecx
 00792BDA    mov         dword ptr fs:[eax],edx
 00792BDD    push        792BF2
 00792BE2    lea         eax,[ebp-8]
 00792BE5    call        @UStrClr
 00792BEA    ret
>00792BEB    jmp         @HandleFinally
>00792BF0    jmp         00792BE2
 00792BF2    mov         eax,ebx
 00792BF4    pop         edi
 00792BF5    pop         esi
 00792BF6    pop         ebx
 00792BF7    mov         esp,ebp
 00792BF9    pop         ebp
 00792BFA    ret
end;*}
Дополнительно добавлю, что та же Ghidra почему-то показывает, что идет именно вызов procedure TMainForm.SettingsLicensesClick, который уже затрагивает sub_00792AD4, при этом на форме в меню вызова такой функции нет, но метод остался.

Ещё про считывание файла лицензии спросил бы, но пока вопрос в этом методе. Во вложении патч для x32dbg с обходом функций.
 

Вложения

  • патч x32dbg.txt
    762 байт · Просмотры: 16
Последнее редактирование:
A typical instinct is: “If the program calls sub_00792AD4(), checks if return == 0, close the form, I can just skip that call or invert the jump so it never closes.))”.
Delphi's codegen does more than just "check a license": exception frames, allocate/fee, global state init, VCL structs.

All side-effect code needs to run + final ret value is always True (1) so the caller never closes the form.
Something like...
Код:
00792BF2    mov   eax, ebx        ; to mov al, 1
00792BF4    pop   edi
00792BF5    pop   esi
00792BF6    pop   ebx
00792BF7    mov   esp, ebp
00792BF9    pop   ebp
00792BFA    ret
 
All side-effect code needs to run + final ret value is always True (1) so the caller never closes the form.
Понял вас, спасибо за совет! Попробую посмотреть по выделенным вами адресам значения регистров в этот момент.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх