vb6 PCode NOP

Author: David Zimmer
Date: 08.29.19 - 10:02pm

I have not yet seen a true one byte NOP instruction for vb6 pcode. Now I have not yet googled for this, but just saw some discussion saying they couldnt find one and I had a fun thought how we can easily MAKE one.

Going back to the source in our previous post consider the following disasm
401D88 Form1.Form_Load:
401D88    F5 04000000           LitI4 0x4
401D8D    F5 03000000           LitI4 0x3
401D92    F5 02000000           LitI4 0x2
401D97    F5 01000000           LitI4 0x1
401D9C    05 0000               ImpAdLdRf Module1.Proc_401DD8
401D9F    0A 01001400           ImpAdCallFPR4 user32.CallWindowProcA
401DA4    3C                    GetLastError  
401DA5    FCC8                  End           <-- nop
401DA7    13                    ExitProcHresult 
This is a perfect example to try, how can we easily eliminate the end call? In this situation we could easily move the ExitProc up but that wont work in very many situations. I want a true one byte nop that has no consequences and can be used anywhere, and I know exactly how to do it easily.

In the opcode handler tables there are plenty of slots which are unused. They are all filled with an invalid opcode handler that just raises an exception just in case they are somehow hit.
ENGINE:66106D14 BE 4F 10 66  _tblByteDisp    dd offset _lblEX_Bos     
ENGINE:66106D18 23 C4 10 66                  dd offset InvalidExCode 

ENGINE:6610C423 InvalidExCode  
ENGINE:6610C423     push    33h
ENGINE:6610C425     call    _EbRaiseExceptionCode
Ok perfect opcode 01 is easy to remember and is a free slot vb will never use. Now we need to find the right block of asm we can re-use?
ENGINE:66105049  _lblEX_StAry                                                                    
ENGINE:66105049     call    ___vbaAryMove@8  
ENGINE:6610504E     xor     eax, eax
ENGINE:66105050     mov     al, [esi]
ENGINE:66105052     inc     esi
ENGINE:66105053     jmp     ds:_tblByteDisp[eax*4]  
Do you see what I see? Got lucky and found this on literally the second try when i scrolled down a few lines from my first instinct of looking at opcode 00 Bos* (see end for details on Bos)

Yeah, all we have to do is change 66106D18 to point to 6610504E and opcode 01 goes from invalid to a perfect one byte nop. (Thats table 5, index 1 for those keeping track)
ENGINE:66108114 tableLead4      dd offset _lblEX_FnStrComp3Var
ENGINE:66108118                 dd offset _lblEX_StAry  
You could patch your runtime on disk or with an injection dll. You could probably even use a sdb shim to patch it but never tried. Anyway since my debugger stuffs a dll into the target process and I am already dynamically locating and patching the opcode tables, this one is a gimmie for use while debugging in vbdec. Going to include it as a little bonus for sure.

Tested in manually in the debugger and worked perfect. Just a fun little find, smallest of tweaks really.

LargeBos: What the heck I am on a roll, you see this instruction everywhere but what does it do? Name makes no sense. Even knowing what it does name still makes no sense.

It takes two bytes off the stream as a word which are cur function start + delta to calculate a new address in the current function.

This address is stored in the vb runtime house keeping area of the stack at ebp-14h. This sets where to resume execution at the asm which is beginning of the next source line for routines which use On Error Resume Next.

I have renamed it ErrNext in my disasm routines.

Final fun fact, there is no On Error Resume Next opcode. They use OnError with the handler address set to 0xFFFF (or -1 to us humans)

Edit: So I did some googling and I found that people did find a natural 2 byte NOP in the form of:
ENGINE:661051E9 _lblEX_CI2UI1          
ENGINE:661051E9                 xor     eax, eax
ENGINE:661051EB                 mov     al, [esi]
ENGINE:661051ED                 inc     esi
ENGINE:661051EE                 jmp     ds:_tblByteDisp[eax*4] 
This is table 2 index 14, so would require a FC14 as referenced in Eternal Bliss VBCrackMe

Comments: (1)

On 08.30.19 - 1:31pm Dave wrote:
Reading up on some old articles on pcode I ran across John Chamberlins Microsofts P-Code Implementation where he has a answer for why there are so many duplicate opcodes:

Altogether there are 775 op-code handlers in VB6. This is possible because many of the 1351 opcodes map to the same handler. The main reason for the overlap is that there are actually two engines: the Visual Basic for Applications engine (in VBA6.DLL) which operates in the design environment and the run-time virtual machine engine (in MSVBVM60.DLL) that is used by executables. Many instructions have one op-code for VBA and a different parallel one for the run-time engine. The two engines have the same functionality with some slight differences mostly attributable to the special needs of the design environment like stepping through code that dont apply to run-time.
Actually after reading more of Johns work, Bos does make sense. He was seeing it generated it always for the IDE in memory pcode, while in compiled versions it only shows up when On Error Resume next is used. he called it beginning of line or by another name would be Beginning of Statement. Makes sense..

Leave Comment:
Email: (not shown)
Message: (Required)
Math Question: 34 + 88 = ? followed by the letter: P 

About Me
More Blogs
Main Site
Yara WorkBench
vbdec dbg updates
vb6 PCode NOP
vb6 API and call backs
how pcode works Pt1
Reversing PCode Args
VB6 PCode Disassembly
VB6 PCode Debugger
UConnect Disable Cell Modem
IDA python over IPC
dns wildcard blocking
64bit IDA Plugins
anterior lines
misc news/updates
Decoders again
CDO.Message Breakpoints
SysAnalyzer Updates
SysAnalyzer and Site Updates
crazy decoder
ida js w/dbg
flash patching #2
JS Graphing
packet reassembly
Delphi IDA Plugin
scdbg IDA integration
API Hash Database
Winmerge plugin
IDACompare Updates
Guest Post @ hexblog
TCP Stream Reassembly
SysAnalyzer Updates
Apilogger Video
Shellcode2Exe trainer
scdbg updates
IDA Javascript w/IDE
Rop Analysis II
scdbg vrs ROP
flash patching
x64 Hooks
micro hook
jmp api+5 *2
SysAnalyzer Updates
InjDll runtime config
C# Asm/Dsm Library
Shellcode Hook Detection
Updates II
Java Hacking
Windows 8
Win7 x64
Graphing ideas
.Net Hacking
Old iDefense Releases
hll shellcode
ActionScript Tips
-patch fu
scdbg ordinal lookup
scdbg -api mode
Peb Module Lists
scdbg vrs Process Injection
GetProcAddress Scanner
scdbg fopen mode
scdbg findsc mode
scdbg MemMonitor
demo shellcodes
scdbg download
api hashs redux
Api hash gen
Retro XSS Chat Codes
Exe as DLL
Olly Plugins
Debugging Explorer
Attach to hidden process
JS Refactoring
Asm and Shellcode in CSharp
Fancy Return Address
PDF Stream Dumper
Malcode Call API by Hash
WinDbg Cheat Sheet
GPG Automation