[原创]VB 远线程注入技术(开源代码)

文章作者:暗夜盛装
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

一个利用VB远线程注入技术实现键盘拦截的例子(无DLL)

1.FORM
Code Language : Visual Basic
  1. Option Explicit
  2. Private Sub cmdLock_Click()
  3. If LockKeyboard(True) Then
  4. cmdLock.Enabled = False
  5. cmdUnLock.Enabled = True
  6. End If
  7. End Sub
  8. Private Sub cmdUnLock_Click()
  9. If LockKeyboard(False) Then
  10. cmdLock.Enabled = True
  11. cmdUnLock.Enabled = False
  12. End If
  13. End Sub
  14. Private Sub Form_Load()
  15. Dim bIsLock As Boolean
  16. bIsLock = GetKeyboardState
  17. cmdLock.Enabled = Not bIsLock
  18. cmdUnLock.Enabled = bIsLock
  19. End Sub
Parsed in 0.006 seconds
2.模块
Code Language : Visual Basic
  1. Option Explicit
  2. '是否包含处理其它键盘消息,True表示处理.
  3. #Const INC_OTHER_KEY = True
  4. '注意,以下所有双版本的API均声明成了 UNICODE 版。 并且许多地方与VB的API浏览器生成的代码有所不同。
  5. Private Declare Function OpenProcess Lib \"kernel32\" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
  6. Private Declare Function ReadProcessMemory Lib \"kernel32\" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
  7. Private Declare Function WriteProcessMemory Lib \"kernel32\" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
  8. Private Declare Function GlobalAddAtom Lib \"kernel32\" Alias \"GlobalAddAtomW\" (ByVal lpString As Long) As Integer
  9. Private Declare Function GlobalDeleteAtom Lib \"kernel32\" (ByVal nAtom As Integer) As Integer
  10. Private Declare Function GlobalFindAtom Lib \"kernel32\" Alias \"GlobalFindAtomW\" (ByVal lpString As Long) As Integer
  11. Private Const TH32CS_SNAPPROCESS = 2
  12. Private Type PROCESSENTRY32W
  13. dwSize       As Long
  14. cntUsage      As Long
  15. h32ProcessID    As Long '  // this process
  16. th32DefaultHeapID  As Long '
  17. h32ModuleID     As Long '  // associated exe
  18. cntThreads     As Long '
  19. th32ParentProcessID As Long '  // this process's parent process
  20. pcPriClassBase   As Long '  // Base priority of process's threads
  21. dwFlags       As Long '
  22. szExeFile(1 To 260) As Integer ' // Path
  23. End Type
  24. Private Declare Function CreateToolhelp32Snapshot Lib \"kernel32\" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
  25. Private Declare Function Process32First Lib \"kernel32\" Alias \"Process32FirstW\" (ByVal hSnapshot As Long, lpPE As PROCESSENTRY32W) As Long
  26. Private Declare Function Process32Next Lib \"kernel32\" Alias \"Process32NextW\" (ByVal hSnapshot As Long, lpPE As PROCESSENTRY32W) As Long
  27. Private Declare Function lstrcmpi Lib \"kernel32\" Alias \"lstrcmpiW\" (lpString1 As Integer, ByVal lpString2 As Long) As Long
  28. Private Declare Function CloseHandle Lib \"kernel32\" (ByVal hObject As Long) As Long
  29. Private Declare Function GetLastError Lib \"kernel32\" () As Long
  30. Private Type LUID
  31. lowpart   As Long
  32. highpart  As Long
  33. End Type
  34. Private Type LUID_AND_ATTRIBUTES
  35. pLuid    As LUID
  36. Attributes As Long
  37. End Type
  38. Private Type TOKEN_PRIVILEGES
  39. PrivilegeCount As Long
  40. Privileges   As LUID_AND_ATTRIBUTES
  41. End Type
  42. Private Const PROCESS_ALL_ACCESS    As Long = &H1F0FFF
  43. Private Const TOKEN_QUERY        As Long = &H8&
  44. Private Const TOKEN_ADJUST_PRIVILEGES  As Long = &H20&
  45. Private Const SE_PRIVILEGE_ENABLED   As Long = &H2
  46. Private Const SE_DEBUG_NAME As String = \"SeDebugPrivilege\"
  47. Private Declare Function GetCurrentProcess Lib \"kernel32\" () As Long
  48. Private Declare Function OpenProcessToken Lib \"advapi32.dll\" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
  49. Private Declare Function LookupPrivilegeValue Lib \"advapi32.dll\" Alias \"LookupPrivilegeValueW\" (ByVal lpSystemName As Long, ByVal lpName As Long, lpLuid As LUID) As Long
  50. Private Declare Function AdjustTokenPrivileges Lib \"advapi32.dll\" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, ByVal PrevState As Long, ByVal N As Long) As Long
  51. Private Declare Function GetModuleHandle Lib \"kernel32\" Alias \"GetModuleHandleW\" (ByVal lpwModuleName As Long) As Long
  52. Private Declare Function GetProcAddress Lib \"kernel32\" (ByVal hModule As Long, ByVal lpProcName As String) As Long
  53. Private Const MEM_COMMIT    As Long = &H1000
  54. Private Const MEM_DECOMMIT   As Long = &H4000
  55. Private Const PAGE_EXECUTE_READWRITE  As Long = &H40
  56. Private Declare Function VirtualAllocEx Lib \"kernel32\" (ByVal ProcessHandle As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
  57. Private Declare Function VirtualFreeEx Lib \"kernel32\" (ByVal ProcessHandle As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
  58. Private Declare Function CreateRemoteThread Lib \"kernel32\" (ByVal hProcess As Long, 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
  59. Private Declare Function WaitForSingleObject Lib \"kernel32\" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
  60. Private Declare Function GetExitCodeThread Lib \"kernel32\" (ByVal hThread As Long, lpExitCode As Long) As Long
  61. #If INC_OTHER_KEY Then
  62. Private Declare Function SetWindowsHookEx Lib \"user32\" Alias \"SetWindowsHookExW\" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
  63. Private Declare Function UnhookWindowsHookEx Lib \"user32\" (ByVal hHook As Long) As Long
  64. Private Declare Function CallNextHookEx Lib \"user32\" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
  65. #End If
  66. Private Const ATOM_FLAG As String = \"HookSysKey\"
  67. Private Const SHELL_FALG As String = \"Winlogon\"
  68. Private Const SHELL_CODE_DWORDLEN = 317   '注入代码所占的双字数
  69. Private Const SHELL_CODE_LENGTH = (SHELL_CODE_DWORDLEN * 4) '字节数
  70. Private Const SHELL_FUNCOFFSET = &H8    '注入代码线程函数偏移量
  71. Private mlShellCode(SHELL_CODE_DWORDLEN - 1) As Long
  72. #If INC_OTHER_KEY Then
  73. Private m_lHookID    As Long       '键盘钩子句柄
  74. Private Type KBDLLHOOKSTRUCT
  75. vkCode     As Long
  76. scanCode    As Long
  77. flags      As Long
  78. time      As Long
  79. dwExtraInfo   As Long
  80. End Type
  81. Private Declare Sub CopyMemory Lib \"kernel32\" Alias \"RtlMoveMemory\" (Destination As Any, Source As Any, ByVal Length As Long)
  82. #End If
  83. '============================================
  84. ' 锁定/解锁键盘
  85. ' 参数:布尔型,真表示锁定
  86. ' 返回:布尔型, 真表示成功
  87. ' 注意:非 Ctrl+Alt+Del 键使用普通钩子技术,因此
  88. '    程序在退出时注意要卸载钩子。
  89. '============================================
  90. Public Function LockKeyboard(ByVal bLock As Boolean) As Boolean
  91. Dim lResult As Long
  92. Dim lStrPtr As Long
  93. Dim iAtom  As Integer
  94. lStrPtr = StrPtr(SHELL_FALG)
  95. iAtom = GlobalFindAtom(lStrPtr)
  96. If iAtom = 0 Then
  97. lResult = InsertAsmCode
  98. Debug.Assert lResult = 0
  99. If lResult Then Exit Function
  100. End If
  101. lStrPtr = StrPtr(ATOM_FLAG)
  102. iAtom = GlobalFindAtom(lStrPtr)
  103. If bLock Then
  104. #If INC_OTHER_KEY Then
  105. '强烈建议:使用了SetWindowsHookEx的话,请编译后再运行!
  106. m_lHookID = SetWindowsHookEx(13, AddressOf LowLevelKeyboardProc, App.hInstance, 0)
  107. #End If
  108. If iAtom = 0 Then iAtom = GlobalAddAtom(lStrPtr)
  109. LockKeyboard = (iAtom <> 0)
  110. Debug.Assert LockKeyboard
  111. Else
  112. #If INC_OTHER_KEY Then
  113. If m_lHookID Then Call UnhookWindowsHookEx(m_lHookID)
  114. #End If
  115. If iAtom Then iAtom = GlobalDeleteAtom(iAtom)
  116. LockKeyboard = iAtom = 0
  117. End If
  118. End Function
  119. Public Function GetKeyboardState() As Boolean
  120. GetKeyboardState = GlobalFindAtom(StrPtr(ATOM_FLAG)) <> 0
  121. End Function
  122. #If INC_OTHER_KEY Then
  123. Private Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  124. Dim KBEvent As KBDLLHOOKSTRUCT
  125. If nCode >= 0 Then
  126. '在这里可以加入实际的过滤条件
  127. CopyMemory KBEvent, ByVal lParam, 20&  'sizeof KBDLLHOOKSTRUCT=20
  128. 'wParam = 消息,如WM_KEYDOWN, WM_KEYUP等
  129. Debug.Print Hex$(KBEvent.vkCode)  'VK_??? 定义的键码
  130. LowLevelKeyboardProc = 1      '1屏蔽,否则应调用CallNextHookEx
  131. Else
  132. LowLevelKeyboardProc = CallNextHookEx(m_lHookID, nCode, wParam, lParam)
  133. End If
  134. End Function
  135. #End If
  136. '----------------------------------------------
  137. ' 远程线程插入函数
  138. ' 功能:向 Winlogon 进程插入远程线程代码,并执行
  139. ' 返回:0表示成功,非0表示标准的系统错误代号
  140. '----------------------------------------------
  141. Private Function InsertAsmCode() As Long
  142. Const WINLOGON As String = \"Winlogon.exe\"
  143. Dim hProcess As Long  '远端进程句柄
  144. Dim hPId  As Long   '远端进程ID
  145. Dim lResult As Long   '一般返回变量
  146. Dim pToken As TOKEN_PRIVILEGES
  147. Dim hToken As Long
  148. Dim hRemoteThread As Long
  149. Dim hRemoteThreadID As Long
  150. Dim lDbResult(1) As Long
  151. Dim lRemoteAddr As Long
  152. '------------------------------------
  153. '取winlogon进程ID
  154. '------------------------------------
  155. hPId = GetProcessIdFromName(WINLOGON)
  156. If hPId = 0 Then
  157. InsertAsmCode = GetLastError
  158. Debug.Assert False
  159. Exit Function
  160. End If
  161. '------------------------------------
  162. '提升本进程权限,以取得对winlogon进程操作的许可
  163. '------------------------------------
  164. lResult = OpenProcessToken(GetCurrentProcess(), _
  165. TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, _
  166. hToken)
  167. Debug.Assert lResult
  168. lResult = LookupPrivilegeValue(0, StrPtr(SE_DEBUG_NAME), pToken.Privileges.pLuid)
  169. Debug.Assert lResult
  170. pToken.PrivilegeCount = 1
  171. pToken.Privileges.Attributes = SE_PRIVILEGE_ENABLED
  172. lResult = AdjustTokenPrivileges(hToken, False, pToken, Len(pToken), 0, 0)
  173. Debug.Assert lResult
  174. '------------------------------------
  175. '打开winlogon进程
  176. '------------------------------------
  177. hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, hPId)
  178. Debug.Assert hProcess
  179. If hProcess Then
  180. '------------------------------------
  181. '初始注入代码
  182. '------------------------------------
  183. Call InitShellCode
  184. '------------------------------------
  185. '远端进程分配内存
  186. '------------------------------------
  187. lRemoteAddr = VirtualAllocEx(hProcess, 0, SHELL_CODE_LENGTH, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
  188. Debug.Assert lRemoteAddr
  189. '------------------------------------
  190. '写入 shell 代码
  191. '------------------------------------
  192. If lRemoteAddr Then
  193. InsertAsmCode = WriteProcessMemory(hProcess, lRemoteAddr, mlShellCode(0), SHELL_CODE_LENGTH, 0)
  194. Else
  195. InsertAsmCode = GetLastError
  196. Exit Function
  197. End If
  198. '------------------------------------
  199. '创建远程线程
  200. '------------------------------------
  201. hRemoteThread = CreateRemoteThread(hProcess, 0, 0, lRemoteAddr + SHELL_FUNCOFFSET, 0, 0, hRemoteThreadID)
  202. If hRemoteThread = 0 Then
  203. InsertAsmCode = GetLastError
  204. Debug.Assert hRemoteThread
  205. Exit Function
  206. End If
  207. '------------------------------------
  208. '等待远程线程
  209. '------------------------------------
  210. Call WaitForSingleObject(hRemoteThread, -1)
  211. Call GetExitCodeThread(hRemoteThread, InsertAsmCode)
  212. Call CloseHandle(hRemoteThread)
  213. '------------------------------------
  214. '释放远端进程内存
  215. '------------------------------------
  216. Call VirtualFreeEx(hProcess, lRemoteAddr, SHELL_CODE_LENGTH, MEM_DECOMMIT)
  217. Else
  218. InsertAsmCode = GetLastError
  219. End If
  220. End Function
  221. '============================================
  222. ' 初始线程代码
  223. '============================================
  224. Private Function InitShellCode() As Long
  225. Const kernel32 As String = \"kernel32.dll\"
  226. Dim hDll  As Long
  227. '------------------------------------
  228. '提取注入代码所需的API函数
  229. '------------------------------------
  230. hDll = GetModuleHandle(StrPtr(kernel32)):         Debug.Assert hDll
  231. mlShellCode(0) = GetProcAddress(hDll, \"GetModuleHandleW\")
  232. mlShellCode(1) = GetProcAddress(hDll, \"GetProcAddress\")
  233. '---------------------------
  234. ' 以下代码由 MASM32 产生
  235. mlShellCode(2) = &HE853&
  236. mlShellCode(3) = &H815B0000
  237. mlShellCode(4) = &H40100EEB
  238. mlShellCode(5) = &H238E800
  239. mlShellCode(6) = &HC00B0000
  240. mlShellCode(7) = &H838D5075
  241. mlShellCode(8) = &H4010B0
  242. mlShellCode(9) = &HD093FF50
  243. mlShellCode(10) = &HF004013
  244. mlShellCode(11) = &HC00BC0B7
  245. mlShellCode(12) = &H683A75
  246. mlShellCode(13) = &H6A020000
  247. mlShellCode(14) = &H8D006A00
  248. mlShellCode(15) = &H4010B083
  249. mlShellCode(16) = &H93FF5000
  250. mlShellCode(17) = &H401090
  251. mlShellCode(18) = &H1874C00B
  252. mlShellCode(19) = &H10C2938D
  253. mlShellCode(20) = &H6A0040
  254. mlShellCode(21) = &H93FF5052
  255. mlShellCode(22) = &H401094
  256. mlShellCode(23) = &H474C00B
  257. mlShellCode(24) = &HAEB0AEB