When analyzing modern malware, the first few instructions often set the tone for the entire session. Vidar stealer doesn’t use complex virtual machines or custom packers for its initial entry point, but rather a sequence of simple assembly-level tricks that exploit how disassemblers interpret code.


The Setup

Here’s what IDA hands you when you first open the binary:

00414E60  74 03    jz   short loc_414E64+1
00414E62  75 01    jnz  short loc_414E64+1

00414E64  B8 E8 26 C2 FE    mov eax, 0FEC226E8h    ; <-- IDA's view
00414E69  FF 74 03 75       push dword ptr [ebx+eax+75h]
...

Looks like a conditional jump followed by some bogus arithmetic. None of it makes sense. That’s the point.


Trick #1: The Opaque Predicate

The jz/jnz pair is the classic opaque predicate. The Zero Flag has exactly two possible states: set or clear. So:

  • ZF = 1 → jz fires → jumps to 0x414E65
  • ZF = 0 → jnz fires → jumps to 0x414E65

Both branches always land on the same address. This is just an unconditional jump dressed up as two conditional ones. The byte at 0x414E64 is never executed.


Trick #2: The Shield Byte

Both jumps target loc_414E64+1 — that’s 0x414E65, one byte past the label, but IDA starts disassembling at 0x414E64.

0x414E64:  B8 E8 26 C2 FE  →  mov eax, 0FEC226E8h

The B8 at 0x414E64 is a shield byte that’s never executed, but it causes the disassembler to swallow the E8 byte that follows as part of an immediate operand. The CPU doesn’t care about IDA’s labeling. It jumps directly to 0x414E65 and sees:

0x414E65:  E8 26 C2 FE FF  →  call 0x401090

E8 is the CALL rel32 opcode. The 4-byte relative offset 0xFFFEC226 resolves to:

0x414E6A + 0xFFFEC226 = 0x00401090

The real first instruction of WinMain is call 0x401090. Every push, add, and mov IDA showed you? Disassembler artifacts, bytes that are actually part of call targets and opaque predicate sequences being misread as instruction bodies.


It’s Chained

After call 0x401090 returns, the next bytes at 0x414E6A are 74 03 75 01, which is another jz/jnz opaque predicate pointing into the middle of yet another mov-as-shield-byte. The pattern repeats at least three times across the block. IDA’s entire view of this region is wrong from the first byte.


Fixing It in IDA

It’s a two-step manual fix per sequence:

  • Press U to undefine the instruction at the shield byte address (e.g. 0x414E64)
  • Move your cursor one byte forward to 0x414E65 and press C to create code

IDA will now decode the real call. Repeat for each chained predicate.

For automation, an IDAPython script scanning for the 74 ?? 75 ?? byte pattern (where both targets resolve to the same address) can patch the shield byte to a NOP and reanalyze.


The Takeaway

What it is What it does to the disassembler
jz X+1 / jnz X+1 Forces execution to bypass the “real” label
Shield byte (B8) Makes the key E8 opcode invisible as a CALL

Neither technique is sophisticated in isolation. The point is that chaining them repeatedly across the function entry turns a straightforward call dispatch into something that looks like corrupted data at a glance.