Advertisement
YAcosta

Tread

Sep 13th, 2024
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ' modMultiThreading.bas - The module provides support for multi-threading.
  2. ' © The trick, 2015
  3.  
  4. Option Explicit
  5.  
  6. Private Type uuid
  7.   data1 As Long
  8.   data2 As Integer
  9.   data3 As Integer
  10.   data4(7) As Byte
  11. End Type
  12.  
  13. Private Type threadData
  14.   lpParameter As Long
  15.   lpAddress   As Long
  16. End Type
  17.  
  18. Private tlsIndex    As Long  ' Index of the item in the TLS. There will be data specific to the thread.
  19. Private lpVBHeader  As Long  ' Pointer to VBHeader structure.
  20. Private hModule     As Long  ' Base address.
  21. Private lpAsm       As Long  ' Pointer to a binary code.
  22.  
  23. ' // Create a new thread
  24. Public Function vbCreateThread(ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
  25. Dim InIDE   As Boolean
  26. If LogActivo Then Call qfLog("vbCreateThread 2: " & lpStartAddress)
  27. Debug.Assert MakeTrue(InIDE)
  28.  
  29.   If InIDE Then
  30.       Dim ret As Long
  31.       ret = DispCallFunc(ByVal 0&, lpStartAddress, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(lpParameter)), CVar(0))
  32.       If ret Then
  33.          Err.Raise ret
  34.       End If
  35.       Exit Function
  36.   End If
  37.  
  38.   ' Alloc new index from thread local storage
  39.  If tlsIndex = 0 Then
  40.       tlsIndex = TlsAlloc()
  41.       If tlsIndex = 0 Then Exit Function
  42.   End If
  43.   ' Get module handle
  44.  If hModule = 0 Then
  45.       hModule = GetModuleHandle(ByVal 0&)
  46.   End If
  47.   ' Create assembler code
  48.  If lpAsm = 0 Then
  49.       lpAsm = CreateAsm()
  50.       If lpAsm = 0 Then Exit Function
  51.   End If
  52.   ' Get pointer to VBHeader and modify
  53.  If lpVBHeader = 0 Then
  54.       lpVBHeader = GetVBHeader()
  55.       If lpVBHeader = 0 Then Exit Function
  56.       ModifyVBHeader lpAsm
  57.   End If
  58.  
  59.   Dim lpThreadData    As Long
  60.   Dim tmpData         As threadData
  61.   ' Alloc thread-specific memory for threadData structure
  62.  lpThreadData = HeapAlloc(GetProcessHeap(), 0, Len(tmpData))
  63.  
  64.   If lpThreadData = 0 Then Exit Function
  65.   ' Set parameters
  66.  tmpData.lpAddress = lpStartAddress
  67.   tmpData.lpParameter = lpParameter
  68.   ' Copy parameters to thread-specific memory
  69.  GetMem8 tmpData, ByVal lpThreadData
  70.   ' Create thread
  71.  vbCreateThread = CreateThread(ByVal lpThreadAttributes, dwStackSize, AddressOf ThreadProc, ByVal lpThreadData, dwCreationFlags, lpThreadId)
  72. End Function
  73. ' // Initialize runtime for new thread and run procedure
  74. Private Function ThreadProc(lpParameter As threadData) As Long
  75.   Dim iid         As uuid
  76.   Dim clsid       As uuid
  77.   Dim lpNewHdr    As Long
  78.   Dim hHeap       As Long
  79.  
  80.   ' Initialize COM
  81.  vbCoInitialize ByVal 0&
  82.   ' IID_IUnknown
  83.  iid.data4(0) = &HC0: iid.data4(7) = &H46
  84.   ' Store parameter to thread local storage
  85.  TlsSetValue tlsIndex, lpParameter
  86.   ' Create the copy of VBHeader
  87.  hHeap = GetProcessHeap()
  88.   lpNewHdr = HeapAlloc(hHeap, 0, &H6A)
  89.   CopyMemory ByVal lpNewHdr, ByVal lpVBHeader, &H6A
  90.   ' Adjust offsets
  91.  Dim names()     As Long
  92.   Dim diff        As Long
  93.   Dim Index       As Long
  94.  
  95.   ReDim names(3)
  96.   diff = lpNewHdr - lpVBHeader
  97.   CopyMemory names(0), ByVal lpVBHeader + &H58, &H10
  98.  
  99.   For Index = 0 To 3
  100.       names(Index) = names(Index) - diff
  101.   Next
  102.  
  103.   CopyMemory ByVal lpNewHdr + &H58, names(0), &H10
  104.   ' This line calls the binary code that runs the asm function.
  105.  VBDllGetClassObject VarPtr(hModule), 0, lpNewHdr, clsid, iid, 0
  106.   ' Free memeory
  107.  HeapFree hHeap, 0, ByVal lpNewHdr
  108.   HeapFree hHeap, 0, lpParameter
  109. End Function
  110. ' // Get VBHeader structure
  111. Private Function GetVBHeader() As Long
  112.   Dim ptr     As Long
  113.  
  114.   ' Get e_lfanew
  115.  GetMem4 ByVal hModule + &H3C, ptr
  116.   ' Get AddressOfEntryPoint
  117.  GetMem4 ByVal ptr + &H28 + hModule, ptr
  118.   ' Get VBHeader
  119.  GetMem4 ByVal ptr + hModule + 1, GetVBHeader
  120. End Function
  121.  
  122. ' // Modify VBHeader to replace Sub Main
  123. Private Sub ModifyVBHeader(ByVal newAddress As Long)
  124.   Dim ptr     As Long
  125.   Dim old     As Long
  126.   Dim flag    As Long
  127.   Dim count   As Long
  128.   Dim size    As Long
  129.  
  130.   ptr = lpVBHeader + &H2C
  131.   ' Are allowed to write in the page
  132.  VirtualProtect ByVal ptr, 4, PAGE_READWRITE, old
  133.   ' Set a new address of Sub Main
  134.  GetMem4 newAddress, ByVal ptr
  135.   VirtualProtect ByVal ptr, 4, old, 0
  136.  
  137.   ' Remove startup form
  138.  GetMem4 ByVal lpVBHeader + &H4C, ptr
  139.  
  140.   ' Get forms count
  141.  GetMem2 ByVal lpVBHeader + &H44, count
  142.  
  143.   Do While count > 0
  144.       ' Get structure size
  145.      GetMem4 ByVal ptr, size
  146.       ' Get flag (unknown5) from current form
  147.      GetMem4 ByVal ptr + &H28, flag
  148.       ' When set, bit 5,
  149.      If flag And &H10 Then
  150.           ' Unset bit 5
  151.          flag = flag And &HFFFFFFEF
  152.           ' Are allowed to write in the page
  153.          VirtualProtect ByVal ptr, 4, PAGE_READWRITE, old
  154.           ' Write changet flag
  155.          GetMem4 flag, ByVal ptr + &H28
  156.           ' Restoring the memory attributes
  157.          VirtualProtect ByVal ptr, 4, old, 0
  158.          
  159.       End If
  160.      
  161.       count = count - 1
  162.       ptr = ptr + size
  163.   Loop
  164. End Sub
  165.  
  166. ' // Create binary code.
  167. Private Function CreateAsm() As Long
  168.   Dim hMod    As Long
  169.   Dim lpProc  As Long
  170.   Dim ptr     As Long
  171.  
  172.   hMod = GetModuleHandle(ByVal StrPtr("kernel32"))
  173.   lpProc = GetProcAddress(hMod, "TlsGetValue")
  174.  
  175.   If lpProc = 0 Then Exit Function
  176.  
  177.   ptr = VirtualAlloc(ByVal 0&, &HF, MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
  178.  
  179.   If ptr = 0 Then Exit Function
  180.  
  181.   ' push  tlsIndex
  182.  ' call  TLSGetValue
  183.  ' pop   ecx
  184.  ' push  DWORD [eax]
  185.  ' push  ecx
  186.  ' jmp   DWORD [eax + 4]
  187.  
  188.   GetMem4 &H68, ByVal ptr + &H0:          GetMem4 &HE800, ByVal ptr + &H4
  189.   GetMem4 &HFF590000, ByVal ptr + &H8:    GetMem4 &H60FF5130, ByVal ptr + &HC
  190.   GetMem4 &H4, ByVal ptr + &H10:          GetMem4 tlsIndex, ByVal ptr + 1
  191.   GetMem4 lpProc - ptr - 10, ByVal ptr + 6
  192.  
  193.   CreateAsm = ptr
  194. End Function
  195.  
  196. Private Function MakeTrue(Value As Boolean) As Boolean
  197.   MakeTrue = True: Value = True
  198. End Function
  199.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement