-1
.text:00401870 ; Attributes: noreturn bp-based frame
.text:00401870
.text:00401870 _wmain          proc near               ; CODE XREF: ___tmainCRTStartup+10A↑p
.text:00401870                 push    ebp
.text:00401871                 mov     ebp, esp
.text:00401873                 call    ds:IsDebuggerPresent
.text:00401879                 test    eax, eax
.text:0040187B                 jz      short loc_401884
.text:0040187D                 call    sub_401730
.text:00401882 ; ---------------------------------------------------------------------------
.text:00401882                 jmp     short loc_401889
.text:00401884 ; ---------------------------------------------------------------------------
.text:00401884
.text:00401884 loc_401884:                             ; CODE XREF: _wmain+B↑j
.text:00401884                 call    sub_4017B0
.text:00401889 ; ---------------------------------------------------------------------------
.text:00401889
.text:00401889 loc_401889:                             ; CODE XREF: _wmain+12↑j
.text:00401889                 xor     eax, eax
.text:0040188B                 pop     ebp
.text:0040188C                 retn
.text:0040188C _wmain          endp
.text:0040188C
.text:0040188C ; ---------------------------------------------------------------------------

Что здесь отвечает за проверку на проверку от отладки ?

Elvin
  • 1,802
  • А вам строка "IsDebuggerPresent" ни о чем не говорит ? – Mike Feb 24 '18 at 13:08
  • @Mike, честно - нет , поэтому сюда и написал – Elvin Feb 24 '18 at 13:09
  • в google translate эту фразу забейте, только через пробел. Хотя imho тут даже знания английского не надо, что бы догадаться что может значить эта фраза – Mike Feb 24 '18 at 13:16
  • @Mike, типо есть ли отладчик – Elvin Feb 24 '18 at 13:18
  • @Mike, меня интересует jz short , что она делает , после проверки наличия отладчика – Elvin Feb 24 '18 at 13:19
  • Ну а больше сказать и нечего, по следующей команде видно, что содержимое eax проверяют на 0. Значит можно предположить, что функция в eax возвращает как раз 0 или 1. А вот какое значение о чем говорит из кода совершенно не ясно. Я бы остерегся предполагать, что 0 говорит об отсутствии (хотя исходя из названия функции вроде как 1 должна означать присутствие). jz производит переход если протестированное значение равно нулю – Mike Feb 24 '18 at 13:22
  • 1
    @Elvin, полезно читать документацию. Просто вбиваете название функции в поисковик, находите что функция делает, какие значения возвращает. Дальше, по ассемблеру желательно почитать про регистр флагов, про то как арифметические и логические операции влияют на регистр флагов, про условные переходы. Ну и про соглашения вызова тоже. Это на один вечер почитать, дальше все станет намного понятнее. – insolor Feb 24 '18 at 19:15

1 Answers1

3

Функция WinAPI IsDebuggerPresent определяет запущена ли программа под отладчиком или нет. Если под отладчиком, из функции возвращается "не ноль", если не под отладчиком - ноль.

В условном языке высокого уровня это например означает что после вызова:

r = IsDebuggerPresent()

в переменной r будет 0, если программа запущена не под отладчиком, и что-то другое, если нет.

В машинном коде все по-другому. Здесь применяются низкоуровневые правила обмена данными, в том числе между кодом и вызываемыми функциями (Application binary interface, ABI). В разных операционных системах эти правила различаются.

Для 32-битного кода под Windows при обращении к функция WinAPI применяются соглашения stdcall и cdecl (см. Соглашения о вызове в Википедии). Если вкратце, то параметры в функции передаются через стек (push перед вызовом функции через call), возвращаемое значение возвращается через регистр eax. stdcall и cdecl различаются только тем, кто выравнивает указатель стека на размер переданных в функцию параметров после окончания работы функции - сама функция или вызывающий код. В данном случае это не существенно, т.к. у функции IsDebuggerPresent вообще нет параметров.

Теперь смотрим снова на ваш код. После вызова функции IsDebuggerPresent проверяется значение в регистре eax. Для этого выполняется команда test eax, eax. По сути это побитовое сравнение числа самого с собой. На первый взгляд это не имеет смысла, но на самом деле, если в eax лежал ноль, то после операции test в регистре флагов устанавливается (становится 1) бит ZF, который как бы говорит, что результат последней операции был нулём. См. вопрос Явные отличия CMP от TEST . См. также Регистр флагов в Википедии.

Дальше идет команда jz short loc_401884. Это команда условного перехода, т.е. переход по определенному адресу, если выполняется какое-то условие. В данном случае переход по адресу метки loc_401884 происходит, если в регистре флагов установлен бит ZF.

Таким образом, если программа запущена не под отладчиком, то в процессе исполнения кода произойдет переход по метке loc_401884. Если под отладчиком, переход не произойдет, дальше выполнится команда jmp short loc_401889, произойдет переход по метке loc_401889.

Как избавиться от проверки? Несколько вариантов:

  1. Убрать вызов функции IsDebuggerPresent, вместо него записать в регистр eax 0. Или заменить на вызов какой-то функции, которая гарантированно вернет 0 (хотя это уже излишнее усложнение).
  2. Заменить test eax, eax на операцию, результатом которой будет ноль. Например xor eax, eax (результат всегда будет 0, в регистр eax запишется 0).
  3. Заменить условный переход jz short loc_401884 на безусловный jmp short loc_401884, чтобы вне зависимости от результата вызова функции IsDebuggerPresent всегда происходил переход на ветку кода, которая обрабатывает вариант, когда программа запущена не под отладчиком.
smellyshovel
  • 5,224
insolor
  • 49,104