mirror of
https://github.com/Vita3K/unicorn.git
synced 2024-11-23 21:39:44 +00:00
VB6 bindings and dynload update w/ uc_context* and uc_free api,… (#715)
* msvc unicorn.def and dynload.c added new uc_context* and uc_free api, includes support for older dlls compiled with uc_context_free (can remove next binary release) * vb6 bindings & x86 32bit sample class for unicorn
This commit is contained in:
parent
47150b6df3
commit
523fb9d9fc
@ -21,3 +21,7 @@ uc_mem_map_ptr
|
||||
uc_mem_unmap
|
||||
uc_mem_protect
|
||||
uc_mem_regions
|
||||
uc_context_alloc
|
||||
uc_context_restore
|
||||
uc_context_save
|
||||
uc_free
|
||||
|
@ -80,6 +80,10 @@ typedef uc_err (*uc_mem_map_ptr_t)(uc_engine *uc, uint64_t address, size_t size,
|
||||
typedef uc_err (*uc_mem_unmap_t)(uc_engine *uc, uint64_t address, size_t size);
|
||||
typedef uc_err (*uc_mem_protect_t)(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
|
||||
typedef uc_err (*uc_mem_regions_t)(uc_engine *uc, uc_mem_region **regions, uint32_t *count);
|
||||
typedef uc_err (*uc_context_alloc_t)(uc_engine *uc, uc_context **context);
|
||||
typedef uc_err (*uc_context_save_t)(uc_engine *uc, uc_context *context);
|
||||
typedef uc_err (*uc_context_restore_t)(uc_engine *uc, uc_context *context);
|
||||
typedef uc_err (*uc_free_t)(void *mem);
|
||||
|
||||
|
||||
static uc_version_t gp_uc_version = NULL;
|
||||
@ -104,7 +108,10 @@ static uc_mem_map_ptr_t gp_uc_mem_map_ptr = NULL;
|
||||
static uc_mem_unmap_t gp_uc_mem_unmap = NULL;
|
||||
static uc_mem_protect_t gp_uc_mem_protect = NULL;
|
||||
static uc_mem_regions_t gp_uc_mem_regions = NULL;
|
||||
|
||||
static uc_context_alloc_t gp_uc_context_alloc = NULL;
|
||||
static uc_context_save_t gp_uc_context_save = NULL;
|
||||
static uc_context_restore_t gp_uc_context_restore = NULL;
|
||||
static uc_free_t gp_uc_free = NULL;
|
||||
|
||||
bool uc_dyn_load(const char* path, int flags)
|
||||
{
|
||||
@ -146,6 +153,14 @@ bool uc_dyn_load(const char* path, int flags)
|
||||
gp_uc_mem_unmap = (uc_mem_unmap_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_mem_unmap");
|
||||
gp_uc_mem_protect = (uc_mem_protect_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_mem_protect");
|
||||
gp_uc_mem_regions = (uc_mem_regions_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_mem_regions");
|
||||
gp_uc_context_alloc = (uc_context_alloc_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_context_alloc");
|
||||
gp_uc_context_save = (uc_context_save_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_context_save");
|
||||
gp_uc_context_restore = (uc_context_restore_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_context_restore");
|
||||
gp_uc_free = (uc_free_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_free");
|
||||
|
||||
//support old compiled dlls
|
||||
if(gp_uc_free==0) gp_uc_free = (uc_free_t)DYNLOAD_GETFUNC(g_dyn_handle, "uc_context_free");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -179,6 +194,11 @@ bool uc_dyn_free(void)
|
||||
gp_uc_mem_unmap = NULL;
|
||||
gp_uc_mem_protect = NULL;
|
||||
gp_uc_mem_regions = NULL;
|
||||
gp_uc_context_alloc = NULL;
|
||||
gp_uc_context_save = NULL;
|
||||
gp_uc_context_restore = NULL;
|
||||
gp_uc_free = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -329,4 +349,23 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count)
|
||||
return gp_uc_mem_regions(uc, regions, count);
|
||||
}
|
||||
|
||||
uc_err uc_context_alloc(uc_engine *uc, uc_context **context){
|
||||
return gp_uc_context_alloc(uc,context);
|
||||
}
|
||||
|
||||
uc_err uc_context_save(uc_engine *uc, uc_context *context)
|
||||
{
|
||||
return gp_uc_context_save(uc,context);
|
||||
}
|
||||
|
||||
uc_err uc_context_restore(uc_engine *uc, uc_context *context){
|
||||
return gp_uc_context_restore(uc,context);
|
||||
}
|
||||
|
||||
uc_err uc_free(void *mem){
|
||||
return gp_uc_free(mem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // DYNLOAD
|
||||
|
11
bindings/vb6/.gitattributes
vendored
Normal file
11
bindings/vb6/.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.frm eol=crlf
|
||||
*.bas eol=crlf
|
||||
*.cls eol=crlf
|
||||
*.ctl eol=crlf
|
||||
*.vbp eol=crlf
|
||||
*.txt eol=crlf
|
||||
*.cpp eol=crlf
|
||||
*.tli eol=crlf
|
||||
*.tlh eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
*.sln eol=crlf
|
50
bindings/vb6/CMemRegion.cls
Normal file
50
bindings/vb6/CMemRegion.cls
Normal file
@ -0,0 +1,50 @@
|
||||
VERSION 1.0 CLASS
|
||||
BEGIN
|
||||
MultiUse = -1 'True
|
||||
Persistable = 0 'NotPersistable
|
||||
DataBindingBehavior = 0 'vbNone
|
||||
DataSourceBehavior = 0 'vbNone
|
||||
MTSTransactionMode = 0 'NotAnMTSObject
|
||||
END
|
||||
Attribute VB_Name = "CMemRegion"
|
||||
Attribute VB_GlobalNameSpace = False
|
||||
Attribute VB_Creatable = True
|
||||
Attribute VB_PredeclaredId = False
|
||||
Attribute VB_Exposed = False
|
||||
'this is for 32bit address space..
|
||||
Public address As Long
|
||||
Public size As Long
|
||||
Public endsAt As Long
|
||||
Public perm As Long
|
||||
|
||||
Function toString() As String
|
||||
toString = "Addr: " & Hex(address) & " Size: " & Hex(size) & " Perm: " & permToString() & " (" & Hex(perm) & ")"
|
||||
End Function
|
||||
|
||||
'Public Enum uc_prot
|
||||
' UC_PROT_NONE = 0
|
||||
' UC_PROT_READ = 1
|
||||
' UC_PROT_WRITE = 2
|
||||
' UC_PROT_EXEC = 4
|
||||
' UC_PROT_ALL = 7
|
||||
'End Enum
|
||||
|
||||
Function permToString() As String
|
||||
|
||||
If perm = 7 Then
|
||||
permToString = "All"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If perm = 0 Then
|
||||
permToString = "None"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If (perm And 1) = 1 Then permToString = "Read "
|
||||
If (perm And 2) = 2 Then permToString = permToString & "Write "
|
||||
If (perm And 4) = 4 Then permToString = permToString & "Exec"
|
||||
|
||||
permToString = Trim(permToString)
|
||||
|
||||
End Function
|
256
bindings/vb6/Form1.frm
Normal file
256
bindings/vb6/Form1.frm
Normal file
@ -0,0 +1,256 @@
|
||||
VERSION 5.00
|
||||
Begin VB.Form Form1
|
||||
Caption = "Form1"
|
||||
ClientHeight = 6720
|
||||
ClientLeft = 60
|
||||
ClientTop = 345
|
||||
ClientWidth = 14220
|
||||
LinkTopic = "Form1"
|
||||
ScaleHeight = 6720
|
||||
ScaleWidth = 14220
|
||||
StartUpPosition = 2 'CenterScreen
|
||||
Begin VB.CommandButton Command1
|
||||
Caption = "Copy"
|
||||
Height = 465
|
||||
Left = 6180
|
||||
TabIndex = 1
|
||||
Top = 6150
|
||||
Width = 1995
|
||||
End
|
||||
Begin VB.ListBox List1
|
||||
BeginProperty Font
|
||||
Name = "Courier New"
|
||||
Size = 11.25
|
||||
Charset = 0
|
||||
Weight = 400
|
||||
Underline = 0 'False
|
||||
Italic = 0 'False
|
||||
Strikethrough = 0 'False
|
||||
EndProperty
|
||||
Height = 5925
|
||||
Left = 150
|
||||
TabIndex = 0
|
||||
Top = 120
|
||||
Width = 13965
|
||||
End
|
||||
End
|
||||
Attribute VB_Name = "Form1"
|
||||
Attribute VB_GlobalNameSpace = False
|
||||
Attribute VB_Creatable = False
|
||||
Attribute VB_PredeclaredId = True
|
||||
Attribute VB_Exposed = False
|
||||
Option Explicit
|
||||
|
||||
'Contributed by: FireEye FLARE team
|
||||
'Author: David Zimmer <david.zimmer@fireeye.com>, <dzzie@yahoo.com>
|
||||
'License: Apache
|
||||
|
||||
Public WithEvents uc As ucIntel32
|
||||
Attribute uc.VB_VarHelpID = -1
|
||||
Dim hContext As Long
|
||||
|
||||
|
||||
'test sample ported from: (requires unicorn 1.0 for success)
|
||||
' https://github.com/unicorn-engine/unicorn/blob/master/tests/unit/test_pc_change.c
|
||||
' https://github.com/unicorn-engine/unicorn/issues/210
|
||||
|
||||
Private Sub Form_Load()
|
||||
|
||||
Dim ecx As Long, edx As Long
|
||||
Dim address As Long, size As Long, endAt As Long
|
||||
Dim b() As Byte, c As Collection, mem As CMemRegion
|
||||
|
||||
Me.Visible = True
|
||||
|
||||
'you can set UNICORN_PATH global variable to load a specific dll, do this before initilizing the class
|
||||
Set uc = New ucIntel32
|
||||
|
||||
If uc.hadErr Then
|
||||
List1.AddItem uc.errMsg
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
List1.AddItem "ucvbshim.dll loaded @" & Hex(uc.hLib)
|
||||
List1.AddItem "Unicorn version: " & uc.Version
|
||||
List1.AddItem "Disassembler available: " & uc.DisasmAvail
|
||||
If uc.major < 1 Then List1.AddItem "Change Eip in hook test requires >= v1.x for success"
|
||||
|
||||
List1.AddItem "Unicorn x86 32bit engine handle: " & Hex(uc.uc)
|
||||
|
||||
' ReDim b(8) 'for clarity in what we are testing..
|
||||
' b(0) = &H41 ' inc ECX @0x1000000
|
||||
' b(1) = &H41 ' inc ECX
|
||||
' b(2) = &H41 ' inc ECX
|
||||
' b(3) = &H41 ' inc ECX @0x1000003
|
||||
' b(4) = &H41 ' inc ECX
|
||||
' b(5) = &H41 ' inc ECX
|
||||
'
|
||||
' b(6) = &H42 ' inc EDX @0x1000006
|
||||
' b(7) = &H42 ' inc EDX
|
||||
|
||||
' #define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx
|
||||
|
||||
'we mash up two different test cases, first the change eip in hook test, then an invalid memory access
|
||||
'note the format accepted by tobytes() is somewhat forgiving (always use 2char hex vals though)
|
||||
b() = toBytes("4141414141414242cc\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a")
|
||||
|
||||
ecx = 3
|
||||
edx = 15
|
||||
address = &H1000000
|
||||
size = &H200000
|
||||
endAt = address + UBound(b) + 1
|
||||
|
||||
If Not uc.mapMem(address, size) Then
|
||||
List1.AddItem "Failed to map in 2mb memory " & uc.errMsg
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
' write machine code to be emulated to memory
|
||||
If Not uc.writeMem(address, b()) Then
|
||||
List1.AddItem "Failed to write code to memory " & uc.errMsg
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
List1.AddItem "starts at: " & uc.disasm(address)
|
||||
|
||||
Dim b2() As Byte
|
||||
If uc.readMem(address, b2, UBound(b) + 1) Then '+1 because ubound is 0 based..
|
||||
List1.AddItem "readMem: " & HexDump(b2, 1)
|
||||
End If
|
||||
|
||||
uc.reg32(ecx_r) = ecx
|
||||
uc.reg32(edx_r) = edx
|
||||
List1.AddItem "start values ECX = " & ecx & " EDX = " & edx
|
||||
|
||||
' trace all instructions
|
||||
uc.addHook hc_code, UC_HOOK_CODE
|
||||
uc.addHook hc_memInvalid, UC_HOOK_MEM_READ_UNMAPPED Or UC_HOOK_MEM_WRITE_UNMAPPED
|
||||
'uc.removeHook UC_HOOK_MEM_READ_UNMAPPED Or UC_HOOK_MEM_WRITE_UNMAPPED
|
||||
uc.addHook hc_int, UC_HOOK_INTR
|
||||
|
||||
List1.AddItem "beginning emulation.."
|
||||
If Not uc.startEmu(address, endAt) Then List1.AddItem uc.errMsg
|
||||
|
||||
ecx = uc.reg32(ecx_r)
|
||||
edx = uc.reg8(dl_r)
|
||||
|
||||
List1.AddItem "ECX: 6 =? " & ecx
|
||||
List1.AddItem "EDX: 17 =? " & edx
|
||||
List1.AddItem uc.dumpFlags
|
||||
If ecx <> 6 Then List1.AddItem "failed to change eip in hook!"
|
||||
|
||||
ReDim b(100) 'this will handle mapping and alignment automatically..
|
||||
uc.writeBlock &H2001, b(), UC_PROT_READ Or UC_PROT_WRITE
|
||||
|
||||
List1.AddItem "Initilizing sharedMemory with: aabbccddeeff0011223344556677889900"
|
||||
sharedMemory() = toBytes("aabbccddeeff0011223344556677889900")
|
||||
ReDim Preserve sharedMemory(&H1000) 'must be 4k bytes aligned...
|
||||
|
||||
If Not uc.mapMemPtr(sharedMemory, &H4000, UBound(sharedMemory)) Then
|
||||
List1.AddItem "Failed to map in host memory " & uc.errMsg
|
||||
Else
|
||||
|
||||
Dim bb As Byte, ii As Integer, ll As Long
|
||||
|
||||
If Not uc.writeByte(&H4001, &H41) Then
|
||||
List1.AddItem "Failed to write byte to shared mem"
|
||||
Else
|
||||
List1.AddItem "Wrote 0x41 to sharedMemory + 1"
|
||||
If uc.readByte(&H4001, bb) Then List1.AddItem "readByte = " & Hex(bb)
|
||||
End If
|
||||
|
||||
'uc.writeInt &H4001, &H4142
|
||||
'If uc.readInt(&H4001, ii) Then List1.AddItem Hex(ii)
|
||||
|
||||
'uc.writeLong &H4001, &H11223344
|
||||
'If uc.readLong(&H4001, ll) Then List1.AddItem Hex(ll)
|
||||
|
||||
Erase b2
|
||||
If uc.readMem(&H4000, b2, 20) Then
|
||||
List1.AddItem "emu read of sharedMemory: " & HexDump(b2, 1)
|
||||
Else
|
||||
List1.AddItem "Failed to readMem on sharedMemory " & uc.errMsg
|
||||
End If
|
||||
|
||||
List1.AddItem "sanity checking host mem: " & HexDump(sharedMemory, 1, , 20)
|
||||
|
||||
End If
|
||||
|
||||
List1.AddItem "Enumerating memory regions..."
|
||||
|
||||
Set c = uc.getMemMap()
|
||||
|
||||
For Each mem In c
|
||||
List1.AddItem mem.toString()
|
||||
Next
|
||||
|
||||
If hContext <> 0 Then
|
||||
List1.AddItem "trying to restore context.."
|
||||
If Not uc.restoreContext(hContext) Then List1.AddItem uc.errMsg
|
||||
List1.AddItem uc.regDump()
|
||||
List1.AddItem "beginning emulation.."
|
||||
If Not uc.startEmu(uc.eip, endAt) Then List1.AddItem uc.errMsg
|
||||
List1.AddItem uc.regDump()
|
||||
List1.AddItem "releasing saved context.."
|
||||
If Not uc.freeContext(hContext) Then List1.AddItem uc.errMsg
|
||||
End If
|
||||
|
||||
Set mem = c(2)
|
||||
If Not uc.changePermissions(mem, UC_PROT_ALL) Then
|
||||
List1.AddItem "Failed to change permissions on second alloc " & uc.errMsg
|
||||
Else
|
||||
List1.AddItem "Changed permissions on second alloc to ALL"
|
||||
List1.AddItem "redumping memory regions to check..."
|
||||
Set c = uc.getMemMap()
|
||||
For Each mem In c
|
||||
List1.AddItem mem.toString()
|
||||
Next
|
||||
End If
|
||||
|
||||
If uc.unMapMem(&H2000) Then
|
||||
List1.AddItem "Successfully unmapped new alloc"
|
||||
Else
|
||||
List1.AddItem "Failed to unmap alloc " & uc.errMsg
|
||||
End If
|
||||
|
||||
List1.AddItem "Mem allocs count now: " & uc.getMemMap().count
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub Command1_Click()
|
||||
Clipboard.Clear
|
||||
Clipboard.SetText lbCopy(List1)
|
||||
End Sub
|
||||
|
||||
Private Sub Form_Unload(Cancel As Integer)
|
||||
'so IDE doesnt hang onto dll and we can recompile in development testing.. if you hit stop this benefit is lost..
|
||||
'do not use this in your real code, only for c dll development..
|
||||
If uc.hLib <> 0 Then FreeLibrary uc.hLib
|
||||
End Sub
|
||||
|
||||
Private Sub uc_CodeHook(ByVal address As Long, ByVal size As Long)
|
||||
|
||||
List1.AddItem "> " & uc.disasm(address)
|
||||
|
||||
If hContext = 0 And address = &H1000003 Then 'change the PC to "inc EDX"
|
||||
List1.AddItem "changing eip to skip last inc ecx's and saving context..."
|
||||
hContext = uc.saveContext()
|
||||
If hContext = 0 Then List1.AddItem "Failed to save context " & uc.errMsg
|
||||
uc.eip = &H1000006
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub uc_Interrupt(ByVal intno As Long)
|
||||
List1.AddItem "Interrupt: " & intno
|
||||
End Sub
|
||||
|
||||
Private Sub uc_InvalidMem(ByVal t As uc_mem_type, ByVal address As Long, ByVal size As Long, ByVal value As Long, continue As Boolean)
|
||||
'continue defaults to false so we can ignore it unless we want to continue..
|
||||
List1.AddItem "Invalid mem access address: " & Hex(address) & " size: " & Hex(size) & " type: " & memType2str(t)
|
||||
End Sub
|
||||
|
||||
Private Sub uc_MemAccess(ByVal t As uc_mem_type, ByVal address As Long, ByVal size As Long, ByVal value As Long)
|
||||
List1.AddItem "mem access: address: " & Hex(address) & " size: " & Hex(size) & " type: " & memType2str(t)
|
||||
End Sub
|
||||
|
42
bindings/vb6/Project1.vbp
Normal file
42
bindings/vb6/Project1.vbp
Normal file
@ -0,0 +1,42 @@
|
||||
Type=Exe
|
||||
Form=Form1.frm
|
||||
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation
|
||||
Module=uc_def; uc_def.bas
|
||||
Module=misc; misc.bas
|
||||
Class=ucIntel32; ucIntel32.cls
|
||||
Class=CMemRegion; CMemRegion.cls
|
||||
IconForm="Form1"
|
||||
Startup="Form1"
|
||||
HelpFile=""
|
||||
ExeName32="vb6Test.exe"
|
||||
Command32=""
|
||||
Name="Project1"
|
||||
HelpContextID="0"
|
||||
CompatibleMode="0"
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
RevisionVer=0
|
||||
AutoIncrementVer=0
|
||||
ServerSupportFiles=0
|
||||
VersionCompanyName="sandsprite"
|
||||
CompilationType=0
|
||||
OptimizationType=0
|
||||
FavorPentiumPro(tm)=0
|
||||
CodeViewDebugInfo=-1
|
||||
NoAliasing=0
|
||||
BoundsCheck=0
|
||||
OverflowCheck=0
|
||||
FlPointCheck=0
|
||||
FDIVCheck=0
|
||||
UnroundedFP=0
|
||||
StartMode=0
|
||||
Unattended=0
|
||||
Retained=0
|
||||
ThreadPerObject=0
|
||||
MaxNumberOfThreads=1
|
||||
|
||||
[MS Transaction Server]
|
||||
AutoRefresh=1
|
||||
|
||||
[fastBuild]
|
||||
fullPath=%ap%\vb6Test.exe
|
5
bindings/vb6/Project1.vbw
Normal file
5
bindings/vb6/Project1.vbw
Normal file
@ -0,0 +1,5 @@
|
||||
Form1 = 39, 35, 1148, 674, , 22, 22, 1090, 631, C
|
||||
uc_def = 56, 12, 1177, 758,
|
||||
misc = 44, 44, 1121, 685,
|
||||
ucIntel32 = 88, 33, 1136, 684,
|
||||
CMemRegion = 110, 110, 1026, 639,
|
71
bindings/vb6/README.txt
Normal file
71
bindings/vb6/README.txt
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
Unicorn engine bindings for VB6
|
||||
|
||||
A sample class for the 32bit x86 emulator is provided.
|
||||
|
||||
Contributed by: FireEye FLARE team
|
||||
Author: David Zimmer <david.zimmer@fireeye.com>, <dzzie@yahoo.com>
|
||||
License: Apache
|
||||
|
||||
' supported api:
|
||||
' ucs_version
|
||||
' ucs_arch_supported
|
||||
' ucs_open
|
||||
' ucs_close
|
||||
' uc_reg_write
|
||||
' uc_reg_read
|
||||
' uc_mem_write
|
||||
' UC_MEM_READ
|
||||
' uc_emu_start
|
||||
' uc_emu_stop
|
||||
' ucs_hook_add
|
||||
' uc_mem_map
|
||||
' uc_hook_del
|
||||
' uc_mem_regions
|
||||
' uc_mem_map_ptr
|
||||
' uc_context_alloc
|
||||
' uc_free
|
||||
' uc_context_save
|
||||
' uc_context_restore
|
||||
' uc_mem_unmap
|
||||
' uc_mem_protect
|
||||
' uc_strerror
|
||||
' uc_errno
|
||||
'
|
||||
' supported hooks:
|
||||
' UC_HOOK_CODE
|
||||
' UC_HOOK_BLOCK
|
||||
' memory READ/WRITE/FETCH
|
||||
' invalid memory access
|
||||
' interrupts
|
||||
'
|
||||
' bonus:
|
||||
' disasm_addr (conditional compile - uses libdasm)
|
||||
' mem_write_block (map and write data auto handles alignment)
|
||||
' get_memMap (wrapper for uc_mem_regions)
|
||||
'
|
||||
|
||||
dependancies: (all in same directory or unicorn package in %windir%)
|
||||
vb6Test.exe
|
||||
ucvbshim.dll _
|
||||
unicorn.dll -
|
||||
libgcc_s_dw2-1.dll \
|
||||
libiconv-2.dll \__ unicorn package
|
||||
libintl-8.dll /
|
||||
libpcre-1.dll /
|
||||
libwinpthread-1.dll_-
|
||||
|
||||
Notes:
|
||||
|
||||
c dll was built using VS2008
|
||||
build notes are included at the top of main.c
|
||||
this dll serves as a stdcall shim so vb6 can access the cdecl api and receive data from the callbacks.
|
||||
|
||||
huge thanks to the unicorn and qemu authors who took on a gigantic task to create this library!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
54
bindings/vb6/example_output.txt
Normal file
54
bindings/vb6/example_output.txt
Normal file
@ -0,0 +1,54 @@
|
||||
ucvbshim.dll loaded @10000000
|
||||
Unicorn version: 1.0
|
||||
Disassembler available: True
|
||||
Unicorn x86 32bit engine handle: 853FD8
|
||||
starts at: 01000000 41 inc ecx
|
||||
readMem: 4141414141414242CC890DAAAAAAAA414A
|
||||
start values ECX = 3 EDX = 15
|
||||
beginning emulation..
|
||||
> 01000000 41 inc ecx
|
||||
> 01000001 41 inc ecx
|
||||
> 01000002 41 inc ecx
|
||||
> 01000003 41 inc ecx
|
||||
changing eip to skip last inc ecx's and saving context...
|
||||
> 01000006 42 inc edx
|
||||
> 01000007 42 inc edx
|
||||
> 01000008 CC int3
|
||||
Interrupt: 3
|
||||
> 01000009 89 0D AA AA AA AA mov [0xaaaaaaaa],ecx
|
||||
Invalid mem access address: AAAAAAAA size: 4 type: Unmapped memory is written to
|
||||
Quit emulation due to WRITE on unmapped memory: uc_emu_start()
|
||||
ECX: 6 =? 6
|
||||
EDX: 17 =? 17
|
||||
EFL 4 P
|
||||
Initilizing sharedMemory with: aabbccddeeff0011223344556677889900
|
||||
Wrote 0x41 to sharedMemory + 1
|
||||
readByte = 41
|
||||
emu read of sharedMemory: AA41CCDDEEFF0011223344556677889900000000
|
||||
sanity checking host mem: AA41CCDDEEFF0011223344556677889900000000
|
||||
Enumerating memory regions...
|
||||
Addr: 1000000 Size: 200000 Perm: All (7)
|
||||
Addr: 2000 Size: 1000 Perm: Read Write (3)
|
||||
Addr: 4000 Size: 1000 Perm: All (7)
|
||||
trying to restore context..
|
||||
eax=0 ecx=6 edx=F ebx=0 esp=0 ebp=0 esi=0 edi=0 eip=1000003 eflags=0 EFL 0
|
||||
beginning emulation..
|
||||
> 01000003 41 inc ecx
|
||||
> 01000004 41 inc ecx
|
||||
> 01000005 41 inc ecx
|
||||
> 01000006 42 inc edx
|
||||
> 01000007 42 inc edx
|
||||
> 01000008 CC int3
|
||||
Interrupt: 3
|
||||
> 01000009 89 0D AA AA AA AA mov [0xaaaaaaaa],ecx
|
||||
Invalid mem access address: AAAAAAAA size: 4 type: Unmapped memory is written to
|
||||
Quit emulation due to WRITE on unmapped memory: uc_emu_start()
|
||||
eax=0 ecx=9 edx=11 ebx=0 esp=0 ebp=0 esi=0 edi=0 eip=1000009 eflags=4 EFL 4 P
|
||||
releasing saved context..
|
||||
Changed permissions on second alloc to ALL
|
||||
redumping memory regions to check...
|
||||
Addr: 1000000 Size: 200000 Perm: All (7)
|
||||
Addr: 2000 Size: 1000 Perm: All (7)
|
||||
Addr: 4000 Size: 1000 Perm: All (7)
|
||||
Successfully unmapped new alloc
|
||||
Mem allocs count now: 2
|
464
bindings/vb6/main.cpp
Normal file
464
bindings/vb6/main.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
|
||||
/*
|
||||
stdcall unicorn engine shim layer for use with VB6 or C#
|
||||
code ripped from unicorn_dynload.c
|
||||
|
||||
Contributed by: FireEye FLARE team
|
||||
Author: David Zimmer <david.zimmer@fireeye.com>, <dzzie@yahoo.com>
|
||||
License: Apache
|
||||
|
||||
Disassembler support can be optionally compiled in using:
|
||||
libdasm (c) 2004 - 2006 jt / nologin.org
|
||||
|
||||
this project has been built with vs2008
|
||||
|
||||
precompiled binaries with disasm support available here:
|
||||
https://github.com/dzzie/libs/tree/master/unicorn_emu
|
||||
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef _WIN64
|
||||
#error vb6 is 32bit only
|
||||
#endif
|
||||
|
||||
#ifdef DYNLOAD
|
||||
#include "./../msvc/unicorn_dynload.h"
|
||||
#else
|
||||
#include <unicorn.h>
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif
|
||||
|
||||
|
||||
//if you compile with VS2008 you will need to add stdint.h and inttypes.h to your compiler include directory
|
||||
//you can find examples here: https://github.com/dzzie/VS_LIBEMU/tree/master/libemu/include
|
||||
|
||||
//if you want to include disassembler support:
|
||||
// 1) install libdasm in your compilers include directory
|
||||
// 2) add libdasm.h/.c to the project (drag and drop into VS project explorer),
|
||||
// 3) remove the comment from the define below.
|
||||
//The vb code detects the changes at runtime.
|
||||
//#define INCLUDE_DISASM
|
||||
|
||||
#ifdef INCLUDE_DISASM
|
||||
#include <libdasm/libdasm.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "msvbvm60.tlh" //so we can use the vb6 collection object
|
||||
|
||||
#define EXPORT comment(linker, "/EXPORT:"__FUNCTION__"="__FUNCDNAME__)
|
||||
|
||||
|
||||
enum hookCatagory{hc_code = 0, hc_block = 1, hc_inst = 2, hc_int = 3, hc_mem = 4, hc_memInvalid = 5};
|
||||
|
||||
//tracing UC_HOOK_CODE & UC_HOOK_BLOCK
|
||||
typedef void (__stdcall *vb_cb_hookcode_t) (uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
|
||||
vb_cb_hookcode_t vbHookcode = 0;
|
||||
vb_cb_hookcode_t vbHookBlock = 0;
|
||||
|
||||
//hooking memory UC_MEM_READ/WRITE/FETCH
|
||||
typedef void (__stdcall *vb_cb_hookmem_t) (uc_engine *uc, uc_mem_type type, uint64_t address, int size,int64_t value, void *user_data);
|
||||
vb_cb_hookmem_t vbHookMem = 0;
|
||||
|
||||
//invalid memory access UC_MEM_*_UNMAPPED and UC_MEM_*PROT events
|
||||
typedef bool (__stdcall *vb_cb_eventmem_t) (uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data);
|
||||
vb_cb_eventmem_t vbInvalidMem = 0;
|
||||
|
||||
//tracing interrupts for uc_hook_intr()
|
||||
typedef void (__stdcall *vb_cb_hookintr_t) (uc_engine *uc, uint32_t intno, void *user_data);
|
||||
vb_cb_hookintr_t vbHookInt = 0;
|
||||
|
||||
/*
|
||||
typedef uint32_t (__stdcall *uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void *user_data); tracing IN instruction of X86
|
||||
typedef void (__stdcall *uc_cb_insn_out_t) (uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data); tracing OUT instruction of X86
|
||||
*/
|
||||
|
||||
//------------------ [ call back proxies ] -------------------------
|
||||
static void c_hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
if(vbHookcode==0) return;
|
||||
vbHookcode(uc,address,size,user_data);
|
||||
}
|
||||
|
||||
static void c_hook_mem(uc_engine *uc, uc_mem_type type,uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
if(vbHookMem==0) return;
|
||||
vbHookMem(uc,type,address,size,value,user_data);
|
||||
}
|
||||
|
||||
static bool c_hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
if(vbInvalidMem==0) return false;
|
||||
return vbInvalidMem(uc,type,address,size,value,user_data);
|
||||
}
|
||||
|
||||
|
||||
static void c_hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
if(vbHookBlock==0) return;
|
||||
vbHookBlock(uc,address,size,user_data);
|
||||
}
|
||||
|
||||
static void c_hook_intr(uc_engine *uc, uint32_t intno, void *user_data)
|
||||
{
|
||||
if(vbHookInt==0) return;
|
||||
vbHookInt(uc,intno,user_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static uint32_t hook_in(uc_engine *uc, uint32_t port, int size, void *user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
//uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, uint64_t begin, uint64_t end, ...);
|
||||
//we need to use a C stub cdecl callback then proxy to the stdcall vb one..
|
||||
//we could get cute with an asm thunk in vb but not worth complexity there are only a couple of them to support..
|
||||
//cdecl callback to vb stdcall callback for tracing
|
||||
uc_err __stdcall ucs_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, uint64_t begin, uint64_t end, int catagory, int instr_id){
|
||||
#pragma EXPORT
|
||||
|
||||
if(catagory == hc_code){
|
||||
if(vbHookcode == 0){
|
||||
if((int)callback==0) return UC_ERR_FETCH_UNMAPPED;
|
||||
vbHookcode = (vb_cb_hookcode_t)callback;
|
||||
}
|
||||
return uc_hook_add(uc,hh,type,c_hook_code,user_data,begin,end);
|
||||
}
|
||||
|
||||
if(catagory == hc_block){
|
||||
if(vbHookBlock == 0){
|
||||
if((int)callback==0) return UC_ERR_FETCH_UNMAPPED;
|
||||
vbHookBlock = (vb_cb_hookcode_t)callback;
|
||||
}
|
||||
return uc_hook_add(uc,hh,type,c_hook_block,user_data,begin,end);
|
||||
}
|
||||
|
||||
if(catagory == hc_mem){ //then it is some combination of memory access hook flags..
|
||||
if(vbHookMem == 0){
|
||||
if((int)callback==0) return UC_ERR_FETCH_UNMAPPED;
|
||||
vbHookMem = (vb_cb_hookmem_t)callback;
|
||||
}
|
||||
return uc_hook_add(uc,hh,type,c_hook_mem,user_data,begin,end);
|
||||
}
|
||||
|
||||
if(catagory == hc_memInvalid){ //then it is some combination of invalid memory access hook flags..
|
||||
if(vbInvalidMem == 0){
|
||||
if((int)callback==0) return UC_ERR_FETCH_UNMAPPED;
|
||||
vbInvalidMem = (vb_cb_eventmem_t)callback;
|
||||
}
|
||||
return uc_hook_add(uc,hh,type,c_hook_mem_invalid,user_data,begin,end);
|
||||
}
|
||||
|
||||
if(catagory == hc_int){
|
||||
if(vbHookInt == 0){
|
||||
if((int)callback==0) return UC_ERR_FETCH_UNMAPPED;
|
||||
vbHookInt = (vb_cb_hookintr_t)callback;
|
||||
}
|
||||
return uc_hook_add(uc,hh,UC_HOOK_INTR,c_hook_intr,user_data,begin,end);
|
||||
}
|
||||
|
||||
return UC_ERR_ARG;
|
||||
}
|
||||
|
||||
unsigned int __stdcall ucs_dynload(char *path){
|
||||
#pragma EXPORT
|
||||
#ifdef DYNLOAD
|
||||
return uc_dyn_load(path, 0);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int __stdcall ucs_version(unsigned int *major, unsigned int *minor){
|
||||
#pragma EXPORT
|
||||
return uc_version(major, minor);
|
||||
}
|
||||
|
||||
bool __stdcall ucs_arch_supported(uc_arch arch){
|
||||
#pragma EXPORT
|
||||
return uc_arch_supported(arch);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_open(uc_arch arch, uc_mode mode, uc_engine **uc){
|
||||
#pragma EXPORT
|
||||
return uc_open(arch, mode, uc);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_close(uc_engine *uc){
|
||||
#pragma EXPORT
|
||||
return uc_close(uc);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_query(uc_engine *uc, uc_query_type type, size_t *result){
|
||||
#pragma EXPORT
|
||||
return uc_query(uc, type, result);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_errno(uc_engine *uc){
|
||||
#pragma EXPORT
|
||||
return uc_errno(uc);
|
||||
}
|
||||
|
||||
const char *__stdcall ucs_strerror(uc_err code){
|
||||
#pragma EXPORT
|
||||
return uc_strerror(code);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_reg_write(uc_engine *uc, int regid, const void *value){
|
||||
#pragma EXPORT
|
||||
return uc_reg_write(uc, regid, value);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_reg_read(uc_engine *uc, int regid, void *value){
|
||||
#pragma EXPORT
|
||||
return uc_reg_read(uc, regid, value);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count){
|
||||
#pragma EXPORT
|
||||
return uc_reg_write_batch(uc, regs, vals, count);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count){
|
||||
#pragma EXPORT
|
||||
return uc_reg_read_batch(uc, regs, vals, count);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size){
|
||||
#pragma EXPORT
|
||||
return uc_mem_write(uc, address, bytes, size);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size){
|
||||
#pragma EXPORT
|
||||
return uc_mem_read(uc, address, bytes, size);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count){
|
||||
#pragma EXPORT
|
||||
return uc_emu_start(uc, begin, until, timeout, count);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_emu_stop(uc_engine *uc){
|
||||
#pragma EXPORT
|
||||
return uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_hook_del(uc_engine *uc, uc_hook hh){
|
||||
#pragma EXPORT
|
||||
return uc_hook_del(uc, hh);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms){
|
||||
#pragma EXPORT
|
||||
return uc_mem_map(uc, address, size, perms);
|
||||
}
|
||||
|
||||
//requires link against v1.0
|
||||
uc_err __stdcall ucs_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr){
|
||||
#pragma EXPORT
|
||||
return uc_mem_map_ptr(uc, address, size, perms, ptr);
|
||||
}
|
||||
|
||||
|
||||
uc_err __stdcall ucs_mem_unmap(uc_engine *uc, uint64_t address, size_t size){
|
||||
#pragma EXPORT
|
||||
return uc_mem_unmap(uc, address, size);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms){
|
||||
#pragma EXPORT
|
||||
return uc_mem_protect(uc, address, size, perms);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count){
|
||||
#pragma EXPORT
|
||||
return uc_mem_regions(uc, regions, count);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_context_alloc(uc_engine *uc, uc_context **context){
|
||||
#pragma EXPORT
|
||||
return uc_context_alloc(uc, context);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_free(void *mem){
|
||||
#pragma EXPORT
|
||||
return uc_free(mem);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_context_save(uc_engine *uc, uc_context *context){
|
||||
#pragma EXPORT
|
||||
return uc_context_save(uc, context);
|
||||
}
|
||||
|
||||
uc_err __stdcall ucs_context_restore(uc_engine *uc, uc_context *context){
|
||||
#pragma EXPORT
|
||||
return uc_context_restore(uc, context);
|
||||
}
|
||||
|
||||
/*
|
||||
char* asprintf(char* format, ...){
|
||||
|
||||
char *ret = 0;
|
||||
|
||||
if(!format) return 0;
|
||||
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
int size = _vscprintf(format, args);
|
||||
|
||||
if(size > 0){
|
||||
size++; //for null
|
||||
ret = (char*)malloc(size+2);
|
||||
if(ret) _vsnprintf(ret, size, format, args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
#ifdef INCLUDE_DISASM
|
||||
int __stdcall disasm_addr(uc_engine *uc, uint32_t va, char *str, int bufLen){
|
||||
#pragma EXPORT
|
||||
uint32_t instr_len = 0;
|
||||
int readLen = 15;
|
||||
uint8_t data[32];
|
||||
INSTRUCTION inst;
|
||||
|
||||
if(bufLen < 100) return -1;
|
||||
|
||||
//longest x86 instruction is 15 bytes, what if at the tail end of an allocation? try to read as much as we can..
|
||||
while(uc_mem_read(uc,va,data,readLen) != 0){
|
||||
readLen--;
|
||||
if(readLen == 0) return -2;
|
||||
}
|
||||
|
||||
instr_len = get_instruction(&inst, data, MODE_32);
|
||||
if( instr_len == 0 ) return -3;
|
||||
|
||||
get_instruction_string(&inst, FORMAT_INTEL, va, str, bufLen);
|
||||
|
||||
/*
|
||||
if(inst.type == INSTRUCTION_TYPE_JMP || inst.type == INSTRUCTION_TYPE_JMPC){
|
||||
if(inst.op1.type == OPERAND_TYPE_IMMEDIATE){
|
||||
if(strlen(str) + 6 < bufLen){
|
||||
if(getJmpTarget(str) < va){
|
||||
strcat(str," ^^");
|
||||
}else{
|
||||
strcat(str," vv");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
return instr_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//maps and write in one shot, auto handles alignment..
|
||||
uc_err __stdcall mem_write_block(uc_engine *uc, uint64_t address, void* data, uint32_t size, uint32_t perm){
|
||||
#pragma EXPORT
|
||||
|
||||
uc_err x;
|
||||
uint64_t base = address;
|
||||
uint32_t sz = size;
|
||||
|
||||
while(base % 0x1000 !=0){
|
||||
base--;
|
||||
if(base==0) break;
|
||||
}
|
||||
|
||||
sz += address-base; //if data starts mid block, we need to alloc more than just size..
|
||||
while(sz % 0x1000 !=0){
|
||||
sz++;
|
||||
}
|
||||
|
||||
x = uc_mem_map(uc, base, sz, perm);
|
||||
if(x) return x;
|
||||
|
||||
x = uc_mem_write(uc, address, (void*)data, size);
|
||||
if(x) return x;
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
void addStr(_CollectionPtr p , char* str){
|
||||
_variant_t vv;
|
||||
vv.SetString(str);
|
||||
p->Add( &vv.GetVARIANT() );
|
||||
}
|
||||
|
||||
uc_err __stdcall get_memMap(uc_engine *uc, _CollectionPtr *pColl){
|
||||
#pragma EXPORT
|
||||
|
||||
uc_mem_region *regions;
|
||||
uint32_t count;
|
||||
char tmp[200]; //max 46 chars used
|
||||
|
||||
uc_err err = uc_mem_regions(uc, ®ions, &count);
|
||||
|
||||
if (err != UC_ERR_OK) return err;
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
sprintf(tmp,"&h%llx,&h%llx,&h%x", regions[i].begin, regions[i].end, regions[i].perms);
|
||||
addStr(*pColl,tmp);
|
||||
}
|
||||
|
||||
//free(regions); //https://github.com/unicorn-engine/unicorn/pull/373#issuecomment-271187118
|
||||
|
||||
uc_free((void*)regions);
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
enum op{
|
||||
op_add = 0,
|
||||
op_sub = 1,
|
||||
op_div = 2,
|
||||
op_mul = 3,
|
||||
op_mod = 4,
|
||||
op_xor = 5,
|
||||
op_and = 6,
|
||||
op_or = 7,
|
||||
op_rsh = 8,
|
||||
op_lsh = 9,
|
||||
op_gt = 10,
|
||||
op_lt = 11,
|
||||
op_gteq = 12,
|
||||
op_lteq = 13
|
||||
};
|
||||
|
||||
unsigned int __stdcall ULong(unsigned int v1, unsigned int v2, int operation){
|
||||
#pragma EXPORT
|
||||
|
||||
switch(operation){
|
||||
case op_add: return v1 + v2;
|
||||
case op_sub: return v1 - v2;
|
||||
case op_div: return v1 / v2;
|
||||
case op_mul: return v1 * v2;
|
||||
case op_mod: return v1 % v2;
|
||||
case op_xor: return v1 ^ v2;
|
||||
case op_and: return v1 & v2;
|
||||
case op_or: return v1 | v2;
|
||||
case op_rsh: return v1 >> v2;
|
||||
case op_lsh: return v1 << v2;
|
||||
case op_gt: return (v1 > v2 ? 1 : 0);
|
||||
case op_lt: return (v1 < v2 ? 1 : 0);
|
||||
case op_gteq: return (v1 >= v2 ? 1 : 0);
|
||||
case op_lteq: return (v1 <= v2 ? 1 : 0);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
325
bindings/vb6/misc.bas
Normal file
325
bindings/vb6/misc.bas
Normal file
@ -0,0 +1,325 @@
|
||||
Attribute VB_Name = "misc"
|
||||
Option Explicit
|
||||
|
||||
Public sharedMemory() As Byte 'in a module so it never goes out of scope and becomes unallocated..
|
||||
|
||||
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
|
||||
Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
|
||||
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
|
||||
Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
|
||||
Public Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
|
||||
|
||||
Enum op
|
||||
op_add = 0
|
||||
op_sub = 1
|
||||
op_div = 2
|
||||
op_mul = 3
|
||||
op_mod = 4
|
||||
op_xor = 5
|
||||
op_and = 6
|
||||
op_or = 7
|
||||
op_rsh = 8
|
||||
op_lsh = 9
|
||||
op_gt = 10
|
||||
op_lt = 11
|
||||
op_gteq = 12
|
||||
op_lteq = 13
|
||||
End Enum
|
||||
|
||||
'unsigned math operations
|
||||
Public Declare Function ULong Lib "ucvbshim.dll" (ByVal v1 As Long, ByVal v2 As Long, ByVal operation As op) As Long
|
||||
|
||||
'this is just a quick way to support x64 numbers in vb6 its lite but can be bulky to work with
|
||||
'if we wanted to really work with x64 values we would compile a library such as the following into the shim layer:
|
||||
' https://github.com/dzzie/libs/tree/master/vb6_utypes
|
||||
|
||||
Private Type Bit64Currency
|
||||
value As Currency
|
||||
End Type
|
||||
|
||||
Private Type Bit64Integer
|
||||
LowValue As Long
|
||||
HighValue As Long
|
||||
End Type
|
||||
|
||||
Global Const LANG_US = &H409
|
||||
|
||||
Function lng2Cur(v As Long) As Currency
|
||||
Dim c As Bit64Currency
|
||||
Dim dl As Bit64Integer
|
||||
dl.LowValue = v
|
||||
dl.HighValue = 0
|
||||
LSet c = dl
|
||||
lng2Cur = c.value
|
||||
End Function
|
||||
|
||||
Function cur2lng(v As Currency) As Long
|
||||
Dim c As Bit64Currency
|
||||
Dim dl As Bit64Integer
|
||||
c.value = v
|
||||
LSet dl = c
|
||||
cur2lng = dl.LowValue
|
||||
End Function
|
||||
|
||||
Function KeyExistsInCollection(c As Collection, val As String) As Boolean
|
||||
On Error GoTo nope
|
||||
Dim t
|
||||
t = c(val)
|
||||
KeyExistsInCollection = True
|
||||
Exit Function
|
||||
nope: KeyExistsInCollection = False
|
||||
End Function
|
||||
|
||||
Function FileExists(path As String) As Boolean
|
||||
On Error GoTo nope
|
||||
|
||||
If Len(path) = 0 Then Exit Function
|
||||
If Right(path, 1) = "\" Then Exit Function
|
||||
If Dir(path, vbHidden Or vbNormal Or vbReadOnly Or vbSystem) <> "" Then FileExists = True
|
||||
|
||||
Exit Function
|
||||
nope: FileExists = False
|
||||
End Function
|
||||
|
||||
Function FileNameFromPath(fullpath) As String
|
||||
Dim tmp
|
||||
If InStr(fullpath, "\") > 0 Then
|
||||
tmp = Split(fullpath, "\")
|
||||
FileNameFromPath = CStr(tmp(UBound(tmp)))
|
||||
End If
|
||||
End Function
|
||||
|
||||
Function GetParentFolder(path) As String
|
||||
Dim tmp, a As Long
|
||||
|
||||
If Right(path, 1) = "\" Then
|
||||
GetParentFolder = path
|
||||
Else
|
||||
a = InStrRev(path, "\")
|
||||
If a > 0 Then
|
||||
GetParentFolder = Mid(path, 1, a)
|
||||
End If
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
Function FolderExists(ByVal path As String) As Boolean
|
||||
On Error GoTo nope
|
||||
If Len(path) = 0 Then Exit Function
|
||||
If Right(path, 1) <> "\" Then path = path & "\"
|
||||
If Dir(path, vbDirectory) <> "" Then FolderExists = True
|
||||
Exit Function
|
||||
nope: FolderExists = False
|
||||
End Function
|
||||
|
||||
Function HexDump(bAryOrStrData, Optional hexOnly = 0, Optional ByVal startAt As Long = 1, Optional ByVal Length As Long = -1) As String
|
||||
Dim s() As String, chars As String, tmp As String
|
||||
On Error Resume Next
|
||||
Dim ary() As Byte
|
||||
Dim offset As Long
|
||||
Const LANG_US = &H409
|
||||
Dim i As Long, tt, h, x
|
||||
|
||||
offset = 0
|
||||
|
||||
If TypeName(bAryOrStrData) = "Byte()" Then
|
||||
ary() = bAryOrStrData
|
||||
Else
|
||||
ary = StrConv(CStr(bAryOrStrData), vbFromUnicode, LANG_US)
|
||||
End If
|
||||
|
||||
If startAt < 1 Then startAt = 1
|
||||
If Length < 1 Then Length = -1
|
||||
|
||||
While startAt Mod 16 <> 0
|
||||
startAt = startAt - 1
|
||||
Wend
|
||||
|
||||
startAt = startAt + 1
|
||||
|
||||
chars = " "
|
||||
For i = startAt To UBound(ary) + 1
|
||||
tt = Hex(ary(i - 1))
|
||||
If Len(tt) = 1 Then tt = "0" & tt
|
||||
tmp = tmp & tt & " "
|
||||
x = ary(i - 1)
|
||||
'chars = chars & IIf((x > 32 And x < 127) Or x > 191, Chr(x), ".") 'x > 191 causes \x0 problems on non us systems... asc(chr(x)) = 0
|
||||
chars = chars & IIf((x > 32 And x < 127), Chr(x), ".")
|
||||
If i > 1 And i Mod 16 = 0 Then
|
||||
h = Hex(offset)
|
||||
While Len(h) < 6: h = "0" & h: Wend
|
||||
If hexOnly = 0 Then
|
||||
push s, h & " " & tmp & chars
|
||||
Else
|
||||
push s, tmp
|
||||
End If
|
||||
offset = offset + 16
|
||||
tmp = Empty
|
||||
chars = " "
|
||||
End If
|
||||
If Length <> -1 Then
|
||||
Length = Length - 1
|
||||
If Length = 0 Then Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
'if read length was not mod 16=0 then
|
||||
'we have part of line to account for
|
||||
If tmp <> Empty Then
|
||||
If hexOnly = 0 Then
|
||||
h = Hex(offset)
|
||||
While Len(h) < 6: h = "0" & h: Wend
|
||||
h = h & " " & tmp
|
||||
While Len(h) <= 56: h = h & " ": Wend
|
||||
push s, h & chars
|
||||
Else
|
||||
push s, tmp
|
||||
End If
|
||||
End If
|
||||
|
||||
HexDump = Join(s, vbCrLf)
|
||||
|
||||
If hexOnly <> 0 Then
|
||||
HexDump = Replace(HexDump, " ", "")
|
||||
HexDump = Replace(HexDump, vbCrLf, "")
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
Public Function toBytes(ByVal hexstr, Optional strRet As Boolean = False)
|
||||
|
||||
'supports:
|
||||
'11 22 33 44 spaced hex chars
|
||||
'11223344 run together hex strings
|
||||
'11,22,33,44 csv hex
|
||||
'\x11,0x22 misc C source rips
|
||||
'
|
||||
'ignores common C source prefixes, operators, delimiters, and whitespace
|
||||
'
|
||||
'not supported
|
||||
'1,2,3,4 all hex chars are must have two chars even if delimited
|
||||
'
|
||||
'a version which supports more formats is here:
|
||||
' https://github.com/dzzie/libs/blob/master/dzrt/globals.cls
|
||||
|
||||
Dim ret As String, x As String, str As String
|
||||
Dim r() As Byte, b As Byte, b1 As Byte
|
||||
Dim foundDecimal As Boolean, tmp, i, a, a2
|
||||
Dim pos As Long, marker As String
|
||||
|
||||
On Error GoTo nope
|
||||
|
||||
str = Replace(hexstr, vbCr, Empty)
|
||||
str = Replace(str, vbLf, Empty)
|
||||
str = Replace(str, vbTab, Empty)
|
||||
str = Replace(str, Chr(0), Empty)
|
||||
str = Replace(str, "{", Empty)
|
||||
str = Replace(str, "}", Empty)
|
||||
str = Replace(str, ";", Empty)
|
||||
str = Replace(str, "+", Empty)
|
||||
str = Replace(str, """""", Empty)
|
||||
str = Replace(str, "'", Empty)
|
||||
str = Replace(str, " ", Empty)
|
||||
str = Replace(str, "0x", Empty)
|
||||
str = Replace(str, "\x", Empty)
|
||||
str = Replace(str, ",", Empty)
|
||||
|
||||
For i = 1 To Len(str) Step 2
|
||||
x = Mid(str, i, 2)
|
||||
If Not isHexChar(x, b) Then Exit Function
|
||||
bpush r(), b
|
||||
Next
|
||||
|
||||
If strRet Then
|
||||
toBytes = StrConv(r, vbUnicode, LANG_US)
|
||||
Else
|
||||
toBytes = r
|
||||
End If
|
||||
|
||||
nope:
|
||||
End Function
|
||||
|
||||
Private Sub bpush(bAry() As Byte, b As Byte) 'this modifies parent ary object
|
||||
On Error GoTo init
|
||||
Dim x As Long
|
||||
|
||||
x = UBound(bAry) '<-throws Error If Not initalized
|
||||
ReDim Preserve bAry(UBound(bAry) + 1)
|
||||
bAry(UBound(bAry)) = b
|
||||
|
||||
Exit Sub
|
||||
|
||||
init:
|
||||
ReDim bAry(0)
|
||||
bAry(0) = b
|
||||
|
||||
End Sub
|
||||
|
||||
Sub push(ary, value) 'this modifies parent ary object
|
||||
On Error GoTo init
|
||||
Dim x
|
||||
|
||||
x = UBound(ary)
|
||||
ReDim Preserve ary(x + 1)
|
||||
|
||||
If IsObject(value) Then
|
||||
Set ary(x + 1) = value
|
||||
Else
|
||||
ary(x + 1) = value
|
||||
End If
|
||||
|
||||
Exit Sub
|
||||
init:
|
||||
ReDim ary(0)
|
||||
If IsObject(value) Then
|
||||
Set ary(0) = value
|
||||
Else
|
||||
ary(0) = value
|
||||
End If
|
||||
End Sub
|
||||
|
||||
|
||||
Public Function isHexChar(hexValue As String, Optional b As Byte) As Boolean
|
||||
On Error Resume Next
|
||||
Dim v As Long
|
||||
|
||||
If Len(hexValue) = 0 Then GoTo nope
|
||||
If Len(hexValue) > 2 Then GoTo nope 'expecting hex char code like FF or 90
|
||||
|
||||
v = CLng("&h" & hexValue)
|
||||
If Err.Number <> 0 Then GoTo nope 'invalid hex code
|
||||
|
||||
b = CByte(v)
|
||||
If Err.Number <> 0 Then GoTo nope 'shouldnt happen.. > 255 cant be with len() <=2 ?
|
||||
|
||||
isHexChar = True
|
||||
|
||||
Exit Function
|
||||
nope:
|
||||
Err.Clear
|
||||
isHexChar = False
|
||||
End Function
|
||||
|
||||
Function hhex(b As Byte) As String
|
||||
hhex = Hex(b)
|
||||
If Len(hhex) = 1 Then hhex = "0" & hhex
|
||||
End Function
|
||||
|
||||
Function rpad(x, i, Optional c = " ")
|
||||
rpad = Left(x & String(i, c), i)
|
||||
End Function
|
||||
|
||||
Function lbCopy(lstBox As Object) As String
|
||||
|
||||
Dim i As Long
|
||||
Dim tmp() As String
|
||||
|
||||
For i = 0 To lstBox.ListCount
|
||||
push tmp, lstBox.List(i)
|
||||
Next
|
||||
|
||||
lbCopy = Join(tmp, vbCrLf)
|
||||
|
||||
End Function
|
||||
|
84
bindings/vb6/msvbvm60.tlh
Normal file
84
bindings/vb6/msvbvm60.tlh
Normal file
@ -0,0 +1,84 @@
|
||||
// Created by Microsoft (R) C/C++ Compiler Version 15.00.21022.08 (2358e5d7).
|
||||
//
|
||||
// d:\projects\col\col\debug\msvbvm60.tlh
|
||||
//
|
||||
// C++ source equivalent of Win32 type library C:\\windows\system32\msvbvm60.dll
|
||||
// compiler-generated file created 03/21/16 at 11:45:20 - DO NOT EDIT!
|
||||
|
||||
#pragma once
|
||||
#pragma pack(push, 8)
|
||||
|
||||
#include <comdef.h>
|
||||
|
||||
//
|
||||
// Forward references and typedefs
|
||||
//
|
||||
|
||||
struct __declspec(uuid("000204ef-0000-0000-c000-000000000046"))
|
||||
/* LIBID */ __VBA;
|
||||
|
||||
struct __declspec(uuid("a4c46780-499f-101b-bb78-00aa00383cbb"))
|
||||
/* dual interface */ _Collection;
|
||||
struct /* coclass */ Collection;
|
||||
|
||||
//
|
||||
// Smart pointer typedef declarations
|
||||
//
|
||||
|
||||
|
||||
_COM_SMARTPTR_TYPEDEF(_Collection, __uuidof(_Collection));
|
||||
|
||||
//
|
||||
// Type library items
|
||||
//
|
||||
|
||||
struct __declspec(uuid("a4c46780-499f-101b-bb78-00aa00383cbb"))
|
||||
_Collection : IDispatch
|
||||
{
|
||||
//
|
||||
// Wrapper methods for error-handling
|
||||
//
|
||||
|
||||
_variant_t Item (
|
||||
VARIANT * Index );
|
||||
HRESULT Add (
|
||||
VARIANT * Item,
|
||||
VARIANT * Key = &vtMissing,
|
||||
VARIANT * Before = &vtMissing,
|
||||
VARIANT * After = &vtMissing );
|
||||
long Count ( );
|
||||
HRESULT Remove (
|
||||
VARIANT * Index );
|
||||
IUnknownPtr _NewEnum ( );
|
||||
|
||||
//
|
||||
// Raw methods provided by interface
|
||||
//
|
||||
|
||||
virtual HRESULT __stdcall raw_Item (
|
||||
/*[in]*/ VARIANT * Index,
|
||||
/*[out,retval]*/ VARIANT * pvarRet ) = 0;
|
||||
virtual HRESULT __stdcall raw_Add (
|
||||
/*[in]*/ VARIANT * Item,
|
||||
/*[in]*/ VARIANT * Key = &vtMissing,
|
||||
/*[in]*/ VARIANT * Before = &vtMissing,
|
||||
/*[in]*/ VARIANT * After = &vtMissing ) = 0;
|
||||
virtual HRESULT __stdcall raw_Count (
|
||||
/*[out,retval]*/ long * pi4 ) = 0;
|
||||
virtual HRESULT __stdcall raw_Remove (
|
||||
/*[in]*/ VARIANT * Index ) = 0;
|
||||
virtual HRESULT __stdcall raw__NewEnum (
|
||||
/*[out,retval]*/ IUnknown * * ppunk ) = 0;
|
||||
};
|
||||
|
||||
struct __declspec(uuid("a4c4671c-499f-101b-bb78-00aa00383cbb"))
|
||||
Collection;
|
||||
// [ default ] interface _Collection
|
||||
|
||||
//
|
||||
// Wrapper method implementations
|
||||
//
|
||||
|
||||
#include "msvbvm60.tli"
|
||||
|
||||
#pragma pack(pop)
|
46
bindings/vb6/msvbvm60.tli
Normal file
46
bindings/vb6/msvbvm60.tli
Normal file
@ -0,0 +1,46 @@
|
||||
// Created by Microsoft (R) C/C++ Compiler Version 15.00.21022.08 (2358e5d7).
|
||||
//
|
||||
// d:\projects\col\col\debug\msvbvm60.tli
|
||||
//
|
||||
// Wrapper implementations for Win32 type library C:\\windows\system32\msvbvm60.dll
|
||||
// compiler-generated file created 03/21/16 at 11:45:20 - DO NOT EDIT!
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// interface _Collection wrapper method implementations
|
||||
//
|
||||
|
||||
inline _variant_t _Collection::Item ( VARIANT * Index ) {
|
||||
VARIANT _result;
|
||||
VariantInit(&_result);
|
||||
HRESULT _hr = raw_Item(Index, &_result);
|
||||
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
|
||||
return _variant_t(_result, false);
|
||||
}
|
||||
|
||||
inline HRESULT _Collection::Add ( VARIANT * Item, VARIANT * Key, VARIANT * Before, VARIANT * After ) {
|
||||
HRESULT _hr = raw_Add(Item, Key, Before, After);
|
||||
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
|
||||
return _hr;
|
||||
}
|
||||
|
||||
inline long _Collection::Count ( ) {
|
||||
long _result = 0;
|
||||
HRESULT _hr = raw_Count(&_result);
|
||||
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
|
||||
return _result;
|
||||
}
|
||||
|
||||
inline HRESULT _Collection::Remove ( VARIANT * Index ) {
|
||||
HRESULT _hr = raw_Remove(Index);
|
||||
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
|
||||
return _hr;
|
||||
}
|
||||
|
||||
inline IUnknownPtr _Collection::_NewEnum ( ) {
|
||||
IUnknown * _result = 0;
|
||||
HRESULT _hr = raw__NewEnum(&_result);
|
||||
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
|
||||
return IUnknownPtr(_result, false);
|
||||
}
|
BIN
bindings/vb6/screenshot.png
Normal file
BIN
bindings/vb6/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
927
bindings/vb6/ucIntel32.cls
Normal file
927
bindings/vb6/ucIntel32.cls
Normal file
@ -0,0 +1,927 @@
|
||||
VERSION 1.0 CLASS
|
||||
BEGIN
|
||||
MultiUse = -1 'True
|
||||
Persistable = 0 'NotPersistable
|
||||
DataBindingBehavior = 0 'vbNone
|
||||
DataSourceBehavior = 0 'vbNone
|
||||
MTSTransactionMode = 0 'NotAnMTSObject
|
||||
END
|
||||
Attribute VB_Name = "ucIntel32"
|
||||
Attribute VB_GlobalNameSpace = False
|
||||
Attribute VB_Creatable = True
|
||||
Attribute VB_PredeclaredId = False
|
||||
Attribute VB_Exposed = False
|
||||
Option Explicit
|
||||
|
||||
'Unicorn Engine x86 32bit wrapper class for vb6
|
||||
|
||||
'Contributed by: FireEye FLARE team
|
||||
'Author: David Zimmer <david.zimmer@fireeye.com>, <dzzie@yahoo.com>
|
||||
'License: Apache
|
||||
|
||||
'we hide the extra labor of x64 conversion from the user. I could simplify
|
||||
'this at the C shim layer but I might write an x64 class later
|
||||
'
|
||||
'since the vb long type only natively supports signed math, I have also handed off a couple
|
||||
'calculations in this class to a C stub just to be safe.
|
||||
'
|
||||
'you can find a full unsigned and x64 safe library for vb6 here:
|
||||
' https://github.com/dzzie/libs/tree/master/vb6_utypes
|
||||
|
||||
Public hLib As Long
|
||||
Public uc As Long
|
||||
Public errMsg As String
|
||||
Public Version As String
|
||||
Public major As Long
|
||||
Public minor As Long
|
||||
|
||||
Private r32 As Variant
|
||||
Private r16 As Variant
|
||||
Private r8 As Variant
|
||||
Private rs_ As Variant
|
||||
Private rs_Name As Variant
|
||||
Private r32_Name As Variant
|
||||
Private r16_Name As Variant
|
||||
Private r8_Name As Variant
|
||||
Private hooks As New Collection
|
||||
Private m_DisasmOk As Boolean
|
||||
|
||||
Event CodeHook(ByVal address As Long, ByVal size As Long)
|
||||
Event BlockHook(ByVal address As Long, ByVal size As Long)
|
||||
Event MemAccess(ByVal t As uc_mem_type, ByVal address As Long, ByVal size As Long, ByVal value As Long)
|
||||
Event InvalidMem(ByVal t As uc_mem_type, ByVal address As Long, ByVal size As Long, ByVal value As Long, ByRef continue As Boolean)
|
||||
Event Interrupt(ByVal intno As Long)
|
||||
|
||||
'our vb enum is 0 based then mapped to the real C values so we can loop them to dump with name lookup
|
||||
'these sub enums also keep the intellisense lists short and focused when reading/writing vals
|
||||
'they are accessed through reg32, reg16, reg8, rs properties, or use raw full enum through reg property
|
||||
'the names of each can be looked up through the reg32n etc properties
|
||||
Public Enum reg_32
|
||||
eax_r = 0
|
||||
ecx_r = 1
|
||||
edx_r = 2
|
||||
ebx_r = 3
|
||||
esp_r = 4
|
||||
ebp_r = 5
|
||||
esi_r = 6
|
||||
edi_r = 7
|
||||
End Enum
|
||||
|
||||
Public Enum reg_16
|
||||
ax_r = 0
|
||||
cx_r = 1
|
||||
dx_r = 2
|
||||
bx_r = 3
|
||||
sp_r = 4
|
||||
bp_r = 5
|
||||
si_r = 6
|
||||
di_r = 7
|
||||
End Enum
|
||||
|
||||
Public Enum reg_8
|
||||
ah_r = 0
|
||||
ch_r = 1
|
||||
dh_r = 2
|
||||
bh_r = 3
|
||||
al_r = 4
|
||||
cl_r = 5
|
||||
dl_r = 6
|
||||
bl_r = 7
|
||||
End Enum
|
||||
|
||||
Public Enum reg_Special
|
||||
CS_r = 0
|
||||
DS_r = 1
|
||||
ES_r = 2
|
||||
FS_r = 3
|
||||
GS_r = 4
|
||||
SS_r = 5
|
||||
IDTR_r = 6
|
||||
GDTR_r = 7
|
||||
LDTR_r = 8
|
||||
End Enum
|
||||
|
||||
Property Get DisasmAvail() As Boolean
|
||||
DisasmAvail = m_DisasmOk
|
||||
End Property
|
||||
|
||||
Property Get lastError() As Long
|
||||
lastError = ucs_errno(uc)
|
||||
End Property
|
||||
|
||||
Property Get hadErr() As Boolean
|
||||
If Len(errMsg) > 0 Then hadErr = True
|
||||
End Property
|
||||
|
||||
Property Get eip() As Long
|
||||
Dim e As uc_err, value As Long
|
||||
e = ucs_reg_read(uc, UC_X86_REG_EIP, value)
|
||||
eip = value
|
||||
End Property
|
||||
|
||||
Property Let eip(v As Long)
|
||||
Dim e As uc_err
|
||||
e = ucs_reg_write(uc, UC_X86_REG_EIP, v)
|
||||
End Property
|
||||
|
||||
Property Get eflags() As Long
|
||||
Dim e As uc_err, value As Long
|
||||
e = ucs_reg_read(uc, UC_X86_REG_EFLAGS, value)
|
||||
eflags = value
|
||||
End Property
|
||||
|
||||
Property Let eflags(v As Long)
|
||||
Dim e As uc_err
|
||||
e = ucs_reg_write(uc, UC_X86_REG_EFLAGS, v)
|
||||
End Property
|
||||
|
||||
|
||||
'full access to all registers if you need it..
|
||||
Property Get reg(r As uc_x86_reg) As Long
|
||||
Dim e As uc_err, value As Long
|
||||
e = ucs_reg_read(uc, r, value)
|
||||
reg = value
|
||||
End Property
|
||||
|
||||
Property Let reg(r As uc_x86_reg, value As Long)
|
||||
Dim e As uc_err
|
||||
e = ucs_reg_write(uc, r, value)
|
||||
End Property
|
||||
|
||||
'32 bit registers
|
||||
Property Get reg32(r As reg_32) As Long
|
||||
Dim e As uc_err, value As Long
|
||||
If r < 0 Or r > UBound(r32) Then Exit Property
|
||||
e = ucs_reg_read(uc, r32(r), value)
|
||||
reg32 = value
|
||||
End Property
|
||||
|
||||
Property Let reg32(r As reg_32, value As Long)
|
||||
Dim e As uc_err
|
||||
If r < 0 Or r > UBound(r32) Then Exit Property
|
||||
e = ucs_reg_write(uc, r32(r), value)
|
||||
End Property
|
||||
|
||||
'16 bit registers
|
||||
Property Get reg16(r As reg_16) As Long
|
||||
Dim e As uc_err, value As Long
|
||||
If r < 0 Or r > UBound(r16) Then Exit Property
|
||||
e = ucs_reg_read(uc, r16(r), value)
|
||||
reg16 = CInt(value)
|
||||
End Property
|
||||
|
||||
Property Let reg16(r As reg_16, ByVal value As Long)
|
||||
Dim e As uc_err
|
||||
value = value And &HFFFF
|
||||
If r < 0 Or r > UBound(r16) Then Exit Property
|
||||
e = ucs_reg_write(uc, r16(r), value)
|
||||
End Property
|
||||
|
||||
'8 bit registers
|
||||
Property Get reg8(r As reg_8) As Long
|
||||
Dim e As uc_err, value As Long
|
||||
If r < 0 Or r > UBound(r8) Then Exit Property
|
||||
e = ucs_reg_read(uc, r8(r), value)
|
||||
reg8 = value
|
||||
End Property
|
||||
|
||||
Property Let reg8(r As reg_8, ByVal value As Long)
|
||||
Dim e As uc_err
|
||||
value = value And &HFF
|
||||
If r < 0 Or r > UBound(r8) Then Exit Property
|
||||
e = ucs_reg_write(uc, r8(r), value)
|
||||
End Property
|
||||
|
||||
'special registers
|
||||
Property Get rs(r As reg_Special) As Long
|
||||
Dim e As uc_err, value As Long
|
||||
If r < 0 Or r > UBound(rs_) Then Exit Property
|
||||
e = ucs_reg_read(uc, rs_(r), value)
|
||||
rs = value
|
||||
End Property
|
||||
|
||||
Property Let rs(r As reg_Special, ByVal value As Long)
|
||||
Dim e As uc_err
|
||||
If r < 0 Or r > UBound(rs_) Then Exit Property
|
||||
e = ucs_reg_write(uc, rs_(r), value)
|
||||
End Property
|
||||
|
||||
|
||||
'reg index to name translation for looping
|
||||
Property Get reg32n(r As reg_32) As String
|
||||
If r < 0 Or r > UBound(r32_Name) Then Exit Property
|
||||
reg32n = r32_Name(r)
|
||||
End Property
|
||||
|
||||
Property Get reg16n(r As reg_16) As String
|
||||
If r < 0 Or r > UBound(r16_Name) Then Exit Property
|
||||
reg16n = r16_Name(r)
|
||||
End Property
|
||||
|
||||
Property Get reg8n(r As reg_8) As String
|
||||
If r < 0 Or r > UBound(r8_Name) Then Exit Property
|
||||
reg8n = r8_Name(r)
|
||||
End Property
|
||||
|
||||
Property Get rsn(r As reg_Special) As String
|
||||
If r < 0 Or r > UBound(rs_Name) Then Exit Property
|
||||
rsn = rs_Name(r)
|
||||
End Property
|
||||
|
||||
Function regDump(Optional includeState As Boolean = True) As String
|
||||
Dim i As Long
|
||||
Dim tmp As String
|
||||
|
||||
For i = 0 To UBound(r32)
|
||||
tmp = tmp & reg32n(i) & "=" & Hex(reg32(i)) & " "
|
||||
'if i mod 3 = 0 and i <> 0 then tmp = tmp & vbcrlf
|
||||
Next
|
||||
|
||||
regDump = tmp
|
||||
|
||||
If includeState Then
|
||||
regDump = regDump & "eip=" & Hex(Me.eip) & " " & dumpFlags()
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
Function dumpFlags() As String
|
||||
|
||||
Dim ret() As String
|
||||
Dim n As Variant
|
||||
Dim i As Long
|
||||
Dim flags As Long
|
||||
|
||||
'http://www.c-jump.com/CIS77/ASM/Instructions/I77_0050_eflags.htm
|
||||
n = Array("C ", 0, "P ", 0, "A ", 0, "Z ", "S ", _
|
||||
"T ", "I ", "D ", "O ", "IOPL ", "IOPL ", "NT ", 0, _
|
||||
"RF ", "VM ", "AC ", "VIF ", "VIP ", "ID ", 0)
|
||||
|
||||
flags = Me.eflags
|
||||
push ret, "EFL " & Hex(flags)
|
||||
|
||||
For i = 0 To 21
|
||||
If flags And ULong(1, i, op_lsh) Then
|
||||
If n(i) <> 0 Then push ret, n(i)
|
||||
End If
|
||||
Next
|
||||
|
||||
dumpFlags = Join(ret, " ")
|
||||
|
||||
|
||||
End Function
|
||||
|
||||
Private Sub Class_Initialize()
|
||||
|
||||
Dim e As uc_err
|
||||
|
||||
'mapping our simplified to real values..
|
||||
r32 = Array(UC_X86_REG_EAX, UC_X86_REG_ECX, UC_X86_REG_EDX, UC_X86_REG_EBX, UC_X86_REG_ESP, UC_X86_REG_EBP, UC_X86_REG_ESI, UC_X86_REG_EDI)
|
||||
r32_Name = Array("eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi")
|
||||
|
||||
r16 = Array(UC_X86_REG_AX, UC_X86_REG_CX, UC_X86_REG_DX, UC_X86_REG_BX, UC_X86_REG_SP, UC_X86_REG_BP, UC_X86_REG_SI, UC_X86_REG_DI)
|
||||
r16_Name = Array("ax", "cx", "dx", "bx", "sp", "bp", "si", "di")
|
||||
|
||||
r8 = Array(UC_X86_REG_AH, UC_X86_REG_CH, UC_X86_REG_DH, UC_X86_REG_BH, UC_X86_REG_AL, UC_X86_REG_CL, UC_X86_REG_DL, UC_X86_REG_Bl)
|
||||
r8_Name = Array("ah", "ch", "dh", "bh", "al", "cl", "dl", "bl")
|
||||
|
||||
rs_ = Array(UC_X86_REG_CS, UC_X86_REG_DS, UC_X86_REG_ES, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_SS, UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR)
|
||||
rs_Name = Array("cs", "ds", "es", "fs", "gs", "ss", "idtr", "gdtr", "ldtr")
|
||||
|
||||
'just to ensure IDE finds the dll before we try to use it...
|
||||
Const dllName As String = "ucvbshim.dll"
|
||||
|
||||
If Len(UNICORN_PATH) = 0 Then
|
||||
UNICORN_PATH = vbNullString
|
||||
ElseIf FolderExists(UNICORN_PATH) Then
|
||||
UNICORN_PATH = UNICORN_PATH & IIf(Right(UNICORN_PATH, 1) = "\", "", "\") & "unicorn.dll"
|
||||
End If
|
||||
|
||||
If hLib = 0 Then
|
||||
hLib = GetModuleHandle(dllName)
|
||||
If hLib = 0 Then
|
||||
hLib = LoadLibrary(GetParentFolder(UNICORN_PATH) & "\" & dllName)
|
||||
If hLib = 0 Then
|
||||
hLib = LoadLibrary(dllName)
|
||||
If hLib = 0 Then
|
||||
errMsg = "Could not load " & dllName
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
If DYNLOAD = 0 Then
|
||||
DYNLOAD = ucs_dynload(UNICORN_PATH)
|
||||
If DYNLOAD = 0 Then
|
||||
errMsg = "Dynamic Loading of unicorn.dll failed " & IIf(Len(UNICORN_PATH) > 0, "path: " & UNICORN_PATH, "")
|
||||
Exit Sub
|
||||
End If
|
||||
End If
|
||||
|
||||
ucs_version major, minor
|
||||
Version = major & "." & minor
|
||||
|
||||
If ucs_arch_supported(UC_ARCH_X86) <> 1 Then
|
||||
errMsg = "UC_ARCH_X86 not supported"
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
e = ucs_open(UC_ARCH_X86, UC_MODE_32, uc)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = "Failed to create new x86 32bit engine instance " & err2str(e)
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
If GetProcAddress(hLib, "disasm_addr") <> 0 Then m_DisasmOk = True
|
||||
|
||||
instances.Add Me, "objptr:" & ObjPtr(Me)
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub Class_Terminate()
|
||||
If uc = 0 Then Exit Sub
|
||||
stopEmu
|
||||
ucs_close uc
|
||||
On Error Resume Next
|
||||
instances.Remove "objptr:" & ObjPtr(Me)
|
||||
End Sub
|
||||
|
||||
Function mapMem(address As Long, size As Long, Optional protection As uc_prot = UC_PROT_ALL) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
|
||||
e = ucs_mem_map(uc, addr, size, protection)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
mapMem = True
|
||||
|
||||
End Function
|
||||
|
||||
'address and size must be 4kb aligned, real buffer must be at least of size, and not go out of scope!
|
||||
Function mapMemPtr(ByRef b() As Byte, address As Long, size As Long, Optional protection As uc_prot = UC_PROT_ALL) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
|
||||
If UBound(b) < size Then
|
||||
errMsg = "Buffer is < size"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If size Mod &H1000 <> 0 Then
|
||||
errMsg = "Size must be 4kb aligned"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If address Mod &H1000 <> 0 Then
|
||||
errMsg = "address must be 4kb aligned"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
e = ucs_mem_map_ptr(uc, addr, size, protection, VarPtr(b(0)))
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
mapMemPtr = True
|
||||
|
||||
End Function
|
||||
|
||||
Function findAlloc(address As Long, Optional inRange As Boolean = False) As CMemRegion
|
||||
Dim m As CMemRegion
|
||||
Dim found As Boolean
|
||||
|
||||
For Each m In getMemMap()
|
||||
If inRange Then
|
||||
If ULong(address, m.address, op_gteq) = 1 And ULong(address, m.address, op_lteq) = 1 Then found = True
|
||||
Else
|
||||
If m.address = address Then found = True
|
||||
End If
|
||||
If found Then
|
||||
Set findAlloc = m
|
||||
Exit Function
|
||||
End If
|
||||
Next
|
||||
End Function
|
||||
|
||||
'we could accept a variant here instead of CMemRegion
|
||||
'if typename(v) = "Long" then enum regions and find cmem, else expect CMemRegion..
|
||||
'would be convient.. or a findAlloc(base as long) as CMemRegion
|
||||
Function changePermissions(m As CMemRegion, newProt As uc_prot)
|
||||
Dim e As uc_err
|
||||
Dim addr64 As Currency
|
||||
|
||||
errMsg = Empty
|
||||
|
||||
If m Is Nothing Then Exit Function
|
||||
|
||||
If newProt = m.perm Then
|
||||
changePermissions = True
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
addr64 = lng2Cur(m.address)
|
||||
|
||||
e = ucs_mem_protect(uc, addr64, m.size, newProt)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
m.perm = newProt
|
||||
changePermissions = True
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
Function unMapMem(base As Long) As Boolean
|
||||
|
||||
Dim m As CMemRegion
|
||||
Dim e As uc_err
|
||||
Dim addr64 As Currency
|
||||
|
||||
errMsg = Empty
|
||||
addr64 = lng2Cur(base)
|
||||
|
||||
For Each m In getMemMap()
|
||||
If m.address = base Then
|
||||
e = ucs_mem_unmap(uc, addr64, m.size)
|
||||
unMapMem = (e = uc_err_ok)
|
||||
If Not unMapMem Then errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
Next
|
||||
|
||||
End Function
|
||||
|
||||
'this function maps and writes (note 32bit only right now)
|
||||
Function writeBlock(address As Long, buf() As Byte, Optional perm As uc_prot = UC_PROT_ALL) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
|
||||
addr = lng2Cur(address)
|
||||
|
||||
errMsg = Empty
|
||||
e = mem_write_block(uc, addr, buf(0), UBound(buf) + 1, perm)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
writeBlock = True
|
||||
|
||||
End Function
|
||||
|
||||
'this function requires the memory already be mapped in, use writeBlock for easier access...
|
||||
Function writeMem(address As Long, buf() As Byte) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
|
||||
e = ucs_mem_write(uc, addr, buf(0), UBound(buf) + 1)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
writeMem = True
|
||||
|
||||
End Function
|
||||
|
||||
Function writeByte(address As Long, b As Byte) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
Dim buf(0) As Byte
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
buf(0) = b
|
||||
|
||||
e = ucs_mem_write(uc, addr, buf(0), 1)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
writeByte = True
|
||||
|
||||
End Function
|
||||
|
||||
Function writeLong(address As Long, value As Long) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
Dim buf(0 To 3) As Byte
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
CopyMemory buf(0), ByVal VarPtr(value), 4
|
||||
|
||||
e = ucs_mem_write(uc, addr, buf(0), 4)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
writeLong = True
|
||||
|
||||
End Function
|
||||
|
||||
Function writeInt(address As Long, value As Integer) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
Dim buf(0 To 1) As Byte
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
CopyMemory buf(0), ByVal VarPtr(value), 2
|
||||
|
||||
e = ucs_mem_write(uc, addr, buf(0), 2)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
writeInt = True
|
||||
|
||||
End Function
|
||||
|
||||
Function readMem(address As Long, ByRef buf() As Byte, ByVal size As Long) As Boolean
|
||||
|
||||
Dim addr As Currency
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
addr = lng2Cur(address)
|
||||
ReDim buf(size - 1) '0 based..
|
||||
|
||||
e = ucs_mem_read(uc, addr, buf(0), UBound(buf) + 1)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
readMem = True
|
||||
|
||||
End Function
|
||||
|
||||
Function readByte(address As Long, ByRef b As Byte) As Boolean
|
||||
|
||||
Dim buf() As Byte
|
||||
|
||||
readMem address, buf, 1
|
||||
If hadErr Then Exit Function
|
||||
|
||||
b = buf(0)
|
||||
readByte = True
|
||||
|
||||
End Function
|
||||
|
||||
Function readLong(address As Long, ByRef retVal As Long) As Boolean
|
||||
|
||||
Dim buf() As Byte
|
||||
|
||||
readMem address, buf, 4
|
||||
If hadErr Then Exit Function
|
||||
|
||||
CopyMemory ByVal VarPtr(retVal), buf(0), 4
|
||||
readLong = True
|
||||
|
||||
End Function
|
||||
|
||||
Function readInt(address As Long, ByRef retVal As Integer) As Boolean
|
||||
|
||||
Dim buf() As Byte
|
||||
|
||||
readMem address, buf, 2
|
||||
If hadErr Then Exit Function
|
||||
|
||||
CopyMemory ByVal VarPtr(retVal), buf(0), 2
|
||||
readInt = True
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
Function saveContext() As Long
|
||||
|
||||
Dim hContext As Long
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
e = ucs_context_alloc(uc, hContext)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
e = ucs_context_save(uc, hContext)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
e = ucs_free(hContext)
|
||||
If e <> uc_err_ok Then errMsg = errMsg & " error freeing context: " & err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
saveContext = hContext
|
||||
|
||||
End Function
|
||||
|
||||
Function restoreContext(hContext As Long) As Boolean
|
||||
|
||||
Dim e As uc_err
|
||||
|
||||
errMsg = Empty
|
||||
e = ucs_context_restore(uc, hContext)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
restoreContext = True
|
||||
|
||||
End Function
|
||||
|
||||
Function freeContext(hContext As Long) As Boolean
|
||||
Dim e As uc_err
|
||||
e = ucs_free(hContext)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Else
|
||||
freeContext = True
|
||||
End If
|
||||
End Function
|
||||
|
||||
|
||||
Function disasm(va As Long, Optional ByRef instrLen As Long) As String
|
||||
|
||||
Dim buf As String, i As Long, b() As Byte
|
||||
Dim dump As String
|
||||
On Error Resume Next
|
||||
|
||||
If Not m_DisasmOk Then
|
||||
disasm = Right("00000000" & Hex(va), 8)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
buf = String(300, Chr(0))
|
||||
|
||||
instrLen = disasm_addr(uc, va, buf, Len(buf))
|
||||
If instrLen < 1 Then
|
||||
Select Case instrLen
|
||||
Case -1: buf = "Buffer to small"
|
||||
Case -2: buf = "Failed to read memory"
|
||||
Case -3: buf = "Failed to disassemble"
|
||||
Case Default: buf = "Unknown error " & instrLen
|
||||
End Select
|
||||
dump = "?? ?? ??"
|
||||
GoTo end_of_func
|
||||
End If
|
||||
|
||||
i = InStr(buf, Chr(0))
|
||||
If i > 2 Then buf = VBA.Left(buf, i - 1) Else buf = Empty
|
||||
|
||||
readMem va, b(), instrLen
|
||||
|
||||
For i = 0 To UBound(b)
|
||||
dump = dump & hhex(b(i)) & " "
|
||||
Next
|
||||
|
||||
end_of_func:
|
||||
disasm = Right("00000000" & Hex(va), 8) & " " & rpad(dump, 25) & buf
|
||||
|
||||
End Function
|
||||
|
||||
Function startEmu(beginAt As Long, endAt As Long, Optional timeout As Long = 0, Optional count As Long = 0) As Boolean
|
||||
|
||||
Dim e As uc_err
|
||||
Dim a As Currency, b As Currency, t As Currency
|
||||
|
||||
a = lng2Cur(beginAt)
|
||||
b = lng2Cur(endAt)
|
||||
t = lng2Cur(timeout)
|
||||
|
||||
errMsg = Empty
|
||||
e = ucs_emu_start(uc, a, b, t, count)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
startEmu = True
|
||||
|
||||
End Function
|
||||
|
||||
Function stopEmu() As Boolean
|
||||
Dim e As uc_err
|
||||
errMsg = Empty
|
||||
e = ucs_emu_stop(uc)
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
stopEmu = True
|
||||
End Function
|
||||
|
||||
|
||||
Function addHook(catagory As hookCatagory, flags As uc_hook_type, Optional beginAt As Long = 1, Optional endAt As Long = 0) As Boolean
|
||||
|
||||
Dim e As uc_err
|
||||
Dim hHook As Long 'handle to remove hook
|
||||
Dim a As Currency, b As Currency
|
||||
|
||||
e = -1
|
||||
a = lng2Cur(beginAt)
|
||||
b = lng2Cur(endAt)
|
||||
errMsg = Empty
|
||||
|
||||
If KeyExistsInCollection(hooks, "flags:" & flags) Then
|
||||
addHook = True
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If catagory = hc_code Then e = ucs_hook_add(uc, hHook, flags, AddressOf code_hook, ObjPtr(Me), a, b, catagory)
|
||||
If catagory = hc_mem Then e = ucs_hook_add(uc, hHook, flags, AddressOf mem_hook, ObjPtr(Me), a, b, catagory)
|
||||
If catagory = hc_memInvalid Then e = ucs_hook_add(uc, hHook, flags, AddressOf invalid_mem_hook, ObjPtr(Me), a, b, catagory)
|
||||
If catagory = hc_block Then e = ucs_hook_add(uc, hHook, flags, AddressOf block_hook, ObjPtr(Me), a, b, catagory)
|
||||
If catagory = hc_int Then e = ucs_hook_add(uc, hHook, flags, AddressOf interrupt_hook, ObjPtr(Me), a, b, catagory)
|
||||
|
||||
If e = -1 Then
|
||||
errMsg = "Unimplemented hook catagory"
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
hooks.Add hHook, "flags:" & flags
|
||||
addHook = True
|
||||
|
||||
End Function
|
||||
|
||||
'actually these appear to use different prototypes for each instruction? (only in/out examples seen...)
|
||||
'what about all the others? not implemented yet in c or vb callback
|
||||
'Function hookInstruction(i As uc_x86_insn, Optional beginAt As Long = 1, Optional endAt As Long = 0) As Boolean
|
||||
'
|
||||
' Dim e As uc_err
|
||||
' Dim hHook As Long 'handle to remove hook
|
||||
' Dim a As Currency, b As Currency
|
||||
'
|
||||
' If i = UC_X86_INS_INVALID Then Exit Function
|
||||
'
|
||||
' e = -1
|
||||
' a = lng2Cur(beginAt)
|
||||
' b = lng2Cur(endAt)
|
||||
' errMsg = Empty
|
||||
'
|
||||
' If KeyExistsInCollection(hooks, "instr:" & i) Then
|
||||
' hookInstruction = True
|
||||
' Exit Function
|
||||
' End If
|
||||
'
|
||||
' e = ucs_hook_add(uc, hHook, UC_HOOK_INSN, AddressOf instruction_hook, ObjPtr(Me), a, b, hc_inst, i)
|
||||
'
|
||||
' If e <> UC_ERR_OK Then
|
||||
' errMsg = err2str(e)
|
||||
' Exit Function
|
||||
' End If
|
||||
'
|
||||
' hooks.Add hHook, "instr:" & i
|
||||
' hookInstruction = True
|
||||
'
|
||||
' End Function
|
||||
|
||||
|
||||
Function removeHook(ByVal flags As uc_hook_type) As Boolean
|
||||
|
||||
On Error Resume Next
|
||||
|
||||
Dim hHook As Long, e As uc_err, wasInstr As Boolean
|
||||
|
||||
errMsg = Empty
|
||||
hHook = hooks("flags:" & flags)
|
||||
|
||||
If hHook = 0 Then
|
||||
hHook = hooks("instr:" & flags) 'maybe it was an instruction hook?
|
||||
If hHook = 0 Then
|
||||
errMsg = "Hook handle not found for supplied flags."
|
||||
Exit Function
|
||||
Else
|
||||
wasInstr = True
|
||||
End If
|
||||
End If
|
||||
|
||||
e = ucs_hook_del(uc, hHook)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
If wasInstr Then
|
||||
hooks.Remove "instr:" & flags
|
||||
Else
|
||||
hooks.Remove "flags:" & flags
|
||||
End If
|
||||
|
||||
removeHook = True
|
||||
|
||||
End Function
|
||||
|
||||
Function getMemMap() As Collection 'of 32bit CMemRegion
|
||||
Dim c As New Collection
|
||||
Dim ret As New Collection
|
||||
Dim mem As CMemRegion
|
||||
Dim e As uc_err
|
||||
Dim s, tmp, v
|
||||
|
||||
errMsg = Empty
|
||||
Set getMemMap = ret
|
||||
|
||||
e = get_memMap(uc, c)
|
||||
|
||||
If e <> uc_err_ok Then
|
||||
errMsg = err2str(e)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
For Each s In c '&h1000000,&h11fffff,&h7 these should always be 32bit safe values created in this class..
|
||||
If Len(s) > 0 Then
|
||||
tmp = Split(s, ",")
|
||||
If UBound(tmp) = 2 Then
|
||||
Set mem = New CMemRegion
|
||||
mem.address = CLng(tmp(0))
|
||||
mem.endsAt = CLng(tmp(1))
|
||||
mem.size = ULong(mem.endsAt, mem.address, op_sub) + 1 'vb native math is signed only..we play it safe..
|
||||
mem.perm = CLng(tmp(2))
|
||||
ret.Add mem
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
'these are internal functions used from the callback in the module to route the message to the event interface
|
||||
'little confusing but in the end easier for the end user...also lays foundation for multiple live instances
|
||||
'(although only one can run at a time since vb is single threaded)
|
||||
|
||||
Friend Function internal_invalid_mem_hook(ByVal t As uc_mem_type, ByVal address As Currency, ByVal size As Long, ByVal value As Currency) As Long
|
||||
Dim addr As Long, v As Long, continue As Boolean
|
||||
addr = cur2lng(address)
|
||||
v = cur2lng(value)
|
||||
RaiseEvent InvalidMem(t, addr, size, v, continue)
|
||||
internal_invalid_mem_hook = IIf(continue, 1, 0)
|
||||
End Function
|
||||
|
||||
Friend Sub internal_mem_hook(ByVal t As uc_mem_type, ByVal address As Currency, ByVal size As Long, ByVal value As Currency)
|
||||
Dim addr As Long, v As Long
|
||||
addr = cur2lng(address)
|
||||
v = cur2lng(value)
|
||||
RaiseEvent MemAccess(t, addr, size, v)
|
||||
End Sub
|
||||
|
||||
Friend Sub internal_code_hook(ByVal address As Currency, ByVal size As Long)
|
||||
Dim addr As Long
|
||||
addr = cur2lng(address)
|
||||
RaiseEvent CodeHook(addr, size)
|
||||
End Sub
|
||||
|
||||
Friend Sub internal_block_hook(ByVal address As Currency, ByVal size As Long)
|
||||
Dim addr As Long
|
||||
addr = cur2lng(address)
|
||||
RaiseEvent BlockHook(addr, size)
|
||||
End Sub
|
||||
|
||||
Friend Sub internal_interrupt_hook(ByVal intno As Long)
|
||||
RaiseEvent Interrupt(intno)
|
||||
End Sub
|
||||
|
2504
bindings/vb6/uc_def.bas
Normal file
2504
bindings/vb6/uc_def.bas
Normal file
File diff suppressed because it is too large
Load Diff
20
bindings/vb6/ucvbshim.sln
Normal file
20
bindings/vb6/ucvbshim.sln
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ucvbshim", "ucvbshim.vcproj", "{6FC797B7-2985-49C8-92CD-CA985AF3511C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6FC797B7-2985-49C8-92CD-CA985AF3511C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6FC797B7-2985-49C8-92CD-CA985AF3511C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6FC797B7-2985-49C8-92CD-CA985AF3511C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6FC797B7-2985-49C8-92CD-CA985AF3511C}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
212
bindings/vb6/ucvbshim.vcproj
Normal file
212
bindings/vb6/ucvbshim.vcproj
Normal file
@ -0,0 +1,212 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="ucvbshim"
|
||||
ProjectGUID="{6FC797B7-2985-49C8-92CD-CA985AF3511C}"
|
||||
RootNamespace="My1"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="./../../include/"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DYNLOAD;"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="./ucvbshim.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="false"
|
||||
ModuleDefinitionFile=""
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
EmbedManifest="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="./../../include/"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;DYNLOAD;"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="./ucvbshim.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
EmbedManifest="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\msvc\unicorn_dynload.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\unicorn\unicorn.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\msvc\unicorn_dynload.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\x86.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
Loading…
Reference in New Issue
Block a user