| 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. | Code:
.486
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.data
szMsgTitle db "IAT Hook", 0
szModule db "user32.dll", 0
szTargetFunc db "GetForegroundWindow", 0
szHooked db "This is in the hooked function - Seems to have worked.", 0
szFail db "Failed.", 0
.data?
IATHook PROTO STDCALL :DWORD, :DWORD, :DWORD
HookProc PROTO STDCALL :LPVOID
.code
HookProc proc Arg1:LPVOID
invoke MessageBox, NULL, addr szHooked, addr szMsgTitle, MB_OK
ret
HookProc endp
IATHook proc pDLLName:LPVOID, pOldAddr:LPVOID, pNewAddr:LPVOID
LOCAL hModule:HANDLE
LOCAL dwVirtualAddr:DWORD
LOCAL dwOrigProtect:DWORD
LOCAL dwDllFound:DWORD
LOCAL dwFunctionFound:DWORD
;Local variables
.if pDLLName == NULL
;Check for NULL pointer
xor eax, eax
ret
.endif
.if pOldAddr == NULL
;Check for NULL pointer
xor eax, eax
ret
.endif
.if pOldAddr == NULL
;Check for NULL pointer
xor eax, eax
ret
.endif
mov dwDllFound, 0
mov dwFunctionFound, 0
;Initialize
invoke GetModuleHandle, NULL
;Get the main module's base address
mov hModule, eax
;Copy it into hModule
mov edi, hModule
assume edi:ptr IMAGE_DOS_HEADER
;Make edi act as IMAGE_DOS_HEADER struct
.if edi == NULL
;Check for NULL pointer
xor eax, eax
ret
;Return 0
.endif
.if [edi].e_magic != IMAGE_DOS_SIGNATURE
;0x4D 0x5A (MZ)
xor eax, eax
ret
;Return 0
.endif
add edi, [edi].e_lfanew
;pNtHeader = (IMAGE_NT_HEADERS*)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);
assume edi:ptr IMAGE_NT_HEADERS
;Make edi act as IMAGE_NT_HEADERS struct
.if edi == NULL
;Check for NULL pointer
xor eax, eax
ret
;Return 0
.endif
.if [edi].Signature != IMAGE_NT_SIGNATURE
;If it's an invalid NT header
;0x50 0x45 0x00 0x00 (PE\0\0)
xor eax, eax
ret
;Return 0
.endif
mov edx, [edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
mov dwVirtualAddr, edx
;Copy the VirtualAddress into dwVirtualAddr
.if dwVirtualAddr == 0
;Invalid virtual address
xor eax, eax
ret
;Return 0
.endif
mov edi, hModule
add edi, dwVirtualAddr
;pImportHeader = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD)pDosHeader + dwVirtualAddr);
assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
;Make edi act as IMAGE_IMPORT_DESCRIPTOR struct
.if edi == NULL
;Check for NULL pointer
xor eax, eax
ret
;Return 0
.endif
.while [edi].Name1 != NULL
mov ecx, hModule
add ecx, [edi].Name1
;pModuleLabel = (char*)((DWORD)pDosHeader + (DWORD)pImportHeader->Name);
mov edx, pDLLName
invoke lstrcmpi, ecx, edx
;Check if this is the DLL we are looking for
.if eax == 0
;This is the DLL we are looking for
mov dwDllFound, 1
;Set ecx to 0, so we know later if the DLL was found
.break
.endif
add edi, sizeof IMAGE_IMPORT_DESCRIPTOR
;Next DLL
.endw
.if dwDllFound != 1
;If the DLL wasn't found
xor eax, eax
ret
;Return 0
.endif
mov edi, [edi].FirstThunk
add edi, hModule
;pThunkData = (IMAGE_THUNK_DATA*)((DWORD)pDosHeader + (DWORD)pImportHeader->FirstThunk);
assume edi:ptr IMAGE_THUNK_DATA
;Make edi act as IMAGE_THUNK_DATA struct
.while [edi].u1.Function != NULL
mov ecx, hModule
add ecx, [edi].u1.Function
mov edx, [edi].u1.Function
;Copies the current functions address (in the IAT table) into edx
.if pOldAddr == edx
;If this is the function we are going to hook
lea ebx, [edi].u1.Function
;Copy the address in the table that the function is stored in, into ebx
invoke VirtualProtect, ebx, 4, PAGE_WRITECOPY, addr dwOrigProtect
;Unprotect the memory where we are going to overwrite (We need 4 bytes --- DWORD = 4 bytes)
mov eax, pNewAddr
;Copy the address we are going to replace it with into eax
mov [ebx], eax
;Patch the address
invoke VirtualProtect, ebx, 4, addr dwOrigProtect, NULL
;Restore the original protection level
mov dwFunctionFound, 1
;Set the value, for later
.break
.endif
add edi, sizeof IMAGE_THUNK_DATA
;Next thunk
.endw
.if dwFunctionFound != 1
;If the function wasn't found
xor eax, eax
ret
;Return 0
.endif
mov eax, 1
ret
;Return 1
;Success
IATHook endp
start:
invoke GetModuleHandle, addr szModule
invoke GetProcAddress, eax, addr szTargetFunc
mov ebx, HookProc
invoke IATHook, addr szModule, eax, ebx ;Redirect GetForegroundWindow (eax) to HookProc (ebx)
.if eax == 0
invoke MessageBox, NULL, addr szFail, addr szMsgTitle, MB_OK
invoke ExitProcess, 0
.endif
;Is now hooked, hopefully.. so lets call it
invoke GetForegroundWindow
invoke ExitProcess, 0
end start |