Timer Patch Solution
Creado el: 18 de enero de 2025
Creado el: 18 de enero de 2025
Analyzing assembly code
I’m examining assembly code from a VB6 program, which employs debugging detection methods like comparing registers and calling functions. Efforts to detect a debugger include examining specific calls and conditional jumps.
Considering patch options
OK, let me see. The user is pondering on skip-calling or modifying a function. Disabling the Timer by setting its interval to zero is another viable approach.
Tweaking the flow
It's clear that changing the conditional jump from "jge" to "jmp" bypasses the call to "ds:__vbaHresultCheckObj," which effectively avoids executing the function.
Tweaking offsets
The user could be suggesting a quick patch by altering the "jge" to "jmp" at offset 0x40B0C1 or adjusting the Timer's interval to zero at offset 0x1726 for simplicity.
Opting for quick tweaks
I’m gathering info on modifying the jump at offset 0x40B0C1 or tweaking the Timer's interval at offset 0x1726. Both methods are swift approaches for making the required changes.
Thought about assembly patching methods for 13 seconds
Below is a concise, practical explanation of how to disable the troublesome timer (or the check) with a simple patch, so that the form does not close repeatedly every few seconds. I’ll outline two common methods:
Looking at the snippet around:
.text:0040B0BD cmp eax, ebx
.text:0040B0BF fnclex
.text:0040B0C1 jge short loc_40B0D5
.text:0040B0C3 mov edx, [ebp+arg_0]
.text:0040B0C6 push 50h ; 'P'
.text:0040B0C8 push offset dword_40201C
.text:0040B0CD push edx
.text:0040B0CE push eax
.text:0040B0CF call ds:__vbaHresultCheckObj
.text:0040B0D5 ; -----------------------------------------------------------------
loc_40B0D5:
The cmp eax, ebx
/jge short loc_40B0D5
sequence checks some condition that, if failing, calls __vbaHresultCheckObj
(which in many VB6 protections can terminate or glitch the program).
If you want to always skip that termination call, you can simply replace jge short loc_40B0D5
(opcodes typically 7D 12
in hex) with an unconditional jump (EB 12
).
Concretely, if you are using a hex editor, search for the bytes 7D 12
at that address and change the 7D
to EB
. In assembly, it changes from:
jge short loc_40B0D5
to
jmp short loc_40B0D5
This way, it never executes the block at 0x40B0C3
and never calls __vbaHresultCheckObj
.
This is often the quickest fix for these repeated calls that forcibly close the form.
As you found, the form uses a standard VB Timer object (Timer1
) with an Interval property of 3000ms (0x0BB8). When that timer expires, it calls into the same anti-debug routine. Disabling (or sabotaging) the timer means that code never fires in the background.
From your research, you see in the VB form structure (often in the data area of the compiled VB program) something like:
00401714 ... "Timer1"
00401724 0B 03 B8 0B 00 00 07 C8 ...
^^^^
Timer Interval
Depending on the exact layout, you’ll see B8 0B
which is 0x0BB8 in little-endian (3000 decimal).
B8 0B
with 00 00
. This yields an Interval of 0, which VB considers invalid, and effectively the timer never fires.FF 7F
(0x7FFF ~ 32767 ms), or any large number. But usually 0 is enough to kill it outright.Either approach stops the repeated calls.
jge
→ jmp
, and done.Timer1.Interval
. You just open a hex editor at the correct offset, change two bytes to 00 00
, and you’re finished.Both approaches work. You only need to apply one of them to keep the form from closing itself every few seconds.
cmp eax, ebx / jge short loc_40B0D5
, change jge
into an unconditional jmp
(hex 7D
→ EB
).0x0BB8
(3000) to 0x0000
. This disables the timer.Either patch should stop the timer-based anti-debug checks from closing the form.