Merge remote-tracking branch 'unicorn-engine/master' into msvc_native

This commit is contained in:
xorstream 2017-01-16 17:26:12 +11:00
commit d56d09e5e1
24 changed files with 5158 additions and 7 deletions

View File

@ -65,3 +65,5 @@ practicalswift: Various cool bugs found by fuzzing
farmdve: Memory leaking fix
Andrew Dutcher: uc_context_{save, restore} API.
Stephen Groat: improved CI setup.
David Zimmer: VB6 binding.

View File

@ -9,6 +9,7 @@ The following bindings are contributed by community.
- MSVC binding: by Zak Escano
- Ruby binding: by Sascha Schirra
- Haskell binding: by Adrian Herrera.
- VB6 binding: David Zimmer.
More bindings created & maintained externally by community are available as follows.

View File

@ -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

View File

@ -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
View 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

View 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
View 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
View 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

View 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
View 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!

View 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
View 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, &regions, &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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

927
bindings/vb6/ucIntel32.cls Normal file
View 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

File diff suppressed because it is too large Load Diff

20
bindings/vb6/ucvbshim.sln Normal file
View 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

View 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>

View File

@ -27,7 +27,7 @@
#define READ_WORD(x) (x & 0xffff)
#define READ_BYTE_H(x) ((x & 0xffff) >> 8)
#define READ_BYTE_L(x) (x & 0xff)
#define WRITE_DWORD(x, w) (x = (x & ~0xffffffff) | (w & 0xffffffff))
#define WRITE_DWORD(x, w) (x = (x & ~0xffffffffLL) | (w & 0xffffffff))
#define WRITE_WORD(x, w) (x = (x & ~0xffff) | (w & 0xffff))
#define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8))
#define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff))

View File

@ -50,9 +50,11 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
void *value = vals[i];
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
*(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0];
else {
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
*(int32_t *)value = READ_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0]);
} else {
switch(regid) {
default: break;
case UC_ARM64_REG_X29:
@ -82,9 +84,11 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals,
for (i = 0; i < count; i++) {
unsigned int regid = regs[i];
const void *value = vals[i];
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) {
ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
else {
} else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) {
WRITE_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value);
} else {
switch(regid) {
default: break;
case UC_ARM64_REG_X29:

View File

@ -0,0 +1,30 @@
#!/usr/bin/python
from unicorn import *
from unicorn.arm64_const import *
from unicorn.x86_const import *
import regress
class Arm64RegReadWriteW0ThroughW30(regress.RegressTest):
"""
Testing the functionality to read/write 32-bit registers in AArch64
See issue #716
"""
def runTest(self):
uc = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
uc.reg_write(UC_ARM64_REG_X0, 0x1234567890abcdef)
self.assertEquals(uc.reg_read(UC_ARM64_REG_X0), 0x1234567890abcdef)
self.assertEquals(uc.reg_read(UC_ARM64_REG_W0), 0x90abcdef)
uc.reg_write(UC_ARM64_REG_X30, 0xa1b2c3d4e5f6a7b8)
self.assertEquals(uc.reg_read(UC_ARM64_REG_W30), 0xe5f6a7b8)
uc.reg_write(UC_ARM64_REG_W30, 0xaabbccdd)
self.assertEquals(uc.reg_read(UC_ARM64_REG_X30), 0xa1b2c3d4aabbccdd)
self.assertEquals(uc.reg_read(UC_ARM64_REG_W30), 0xaabbccdd)
if __name__ == '__main__':
regress.main()

View File

@ -38,7 +38,7 @@ class FpVfpDisabled(regress.RegressTest):
uc.mem_map(address, mem_size)
uc.mem_write(address, code_bytes)
uc.reg_write(UC_ARM_REG_SP, address + mem_size)
uc.emu_start(address, address + len(code_bytes))
uc.emu_start(address + 1, address + len(code_bytes))
if __name__ == '__main__':
regress.main()