Jump to content

Hooking Functions with AutoIt


CakeOfChaos
 Share

Recommended Posts

Hello, I like you to show a possibility to hook external functions in other processes. It's EXTREMELY buggy, but it works. I think it'll take a lot of time to find all the bugs, but some guys wanted to help me because I won't have much time soon.

You have to modify the NomadMemory.au3 because it does not work in conjunction with the WinAPI.au3. There are 2 constants which get redeclared when including both scripts. You have to comment them out.

Ok, I think the most of you think: How does it work?

I will shortly try to explain it:

AutoitFunction->DllCallbackRegister->DllCallbackgetPtr()

With these functions you are able to load the address of your function. But how does we load it into the other process? The answer is quite simple: We do not load it. We are calling the function with CreateRemoteThread from the other Process :)

First we have to call OpenProcess by Injecting Assembler Code into the process. Then we call this code and save the handle.

After that we create a CodeCave. This is done by allocating space in the RAM and write there our code. Following we write in the beginning of the target a jump to our code.

The injected code will look like this:

PUSH 0
PUSH 0
PUSH ESP
PUSH 620000
PUSH 0
PUSH 0
PUSH DWORD PTR DS:[3E0000]
CALL kernel32.CreateRemoteThread
PUSH EAX
PUSH -1
PUSH EAX
CALL kernel32.WaitForSingleObject
CALL kernel32.CloseHandle
MOV EDI,EDI
PUSH EBP
MOV EBP,ESP
JMP USER32.75CAFEB3

You can (hopefully) see, that we are creating a Thread and waiting INFINITE until it ends. Then we are executing the overwritten Code and jump back to our functions. the parameter for the Thread is the ESP-Register. With this we can load and modify the parameters on the stack.

Unfortunately Autoit often crashes when executing the thread or hanging around without doing something.

Thats the secret of Hooking with Autoit :D in the include-file are also some functions for modifying strings in the RAM.

Ok, here is the first Example for Hooking the MessageboxA-Function:

#include "Hooking.au3"
;===================>Global Variables
Global $hHook, $hProc
Global $pString[2] = [0, 0] ;the first element holds the address and the second the length, so its easier to call the _DelString() Function
Global $sProcessName = "HookingTest.exe" ;our target process
;===========>
SetPrivilege("SeDebugPrivilege", 1) ;too trivial
$lpMsgBoxA = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("user32.dll"), "MessageBoxA") ;we are reading the address of MessageBoxA in the RAM
$callback = DllCallbackRegister("myHookFunc", "none", "dword") ;we are registering the callback function
If @error Then
    MsgBox(16, "ERROR", "Couldn't initialize Callback")
    Exit
EndIf
$ptr = DllCallbackGetPtr($callback)
_VirtualProtect(Number($ptr), 94) ;we have to unprotect the Callbackfunction
$hProc = _OpenProcess($sProcessName) ;we have to open the process
$hHook = _SetHook(number($lpMsgBoxA), 5, Number($ptr), "int;int;int;int", $hProc) ;we are going to hook the MessageBoxA-Function
Do
    Sleep(1000)
until NOT ProcessExists($sProcessName) ;waiting
Func myHookFunc($iParam) ;=>our HookFunction
    If $pString[0] <> 0 Then _DelString($pString[0], $pString[1], $hProc) ;free the old string
    _GetParameter($iParam, $hHook, $hProc) ;get the parameter from the stack
    $sText = _ReadString(DllStructgetdata($hHook[5], 3), $hProc) ;read the content of the messagebox
    $sText = "OWNED BY AUTOIT ;)" & @crlf & "originalText: " & $sText ;modify it
    $pString = _CreateNewString($sText, $hProc) ;create space for it and write it in the other process
    DllStructSetData($hHook[5], 3, $pString[0]) ;set new string as parameter
    _SetParameter($iParam, $hHook, $hProc) ;and write it ;)
    return ;works much better with return
EndFunc

When executing this function we load the parameters and create a new string. After this we replace the old string.

I used this program for testing it (C++, minGW and Code::Blocks):

#include <windows.h>

int main()
{
    while (1)
    {
        system("pause");
        MessageBoxA(NULL, "the text", "the title", NULL);
    }
    return 0;
}

The Include-File is in the attachement. I wish you much fun when debugging these programs ;) It's extremely buggy but this example should work properly (I am using Windows 7 Ultimate 64-Bit).

PS: There are a lot of number-calls. I've used them because sometimes Autoit did not convert variables properly.

mfg CakeOfChaos (alias @night@)

Hooking.au3

Edited by CakeOfChaos
Link to comment
Share on other sites

Code injection and hooking has been discussed a lot before, so what you're doing is not exactly new. Although no one has quite gone this route by have the remote process create a thread within AutoIt. As you've seen, AutoIt is not thread friendly. Why not use some other communication solution such as messages or named pipes (or event CreateProcess to invoke another instance of the AutoIt script) to have the remote process feed AutoIt the data you are looking for, and then AutoIt can properly execute functions without trying to multithread.

Link to comment
Share on other sites

Code injection and hooking has been discussed a lot before, so what you're doing is not exactly new.

I'm sorry. I did not find anything with google.

Although no one has quite gone this route by have the remote process create a thread within AutoIt. As you've seen, AutoIt is not thread friendly. Why not use some other communication solution such as messages or named pipes (or event CreateProcess to invoke another instance of the AutoIt script) to have the remote process feed AutoIt the data you are looking for, and then AutoIt can properly execute functions without trying to multithread.

In the beginning I wanted to write a Dll which communicates with Winsocks. But I thought this would be too slow. But if I use C++ it wouldn't be only Autoit :)

Well, I keep experimenting with Hooks...

Link to comment
Share on other sites

Nothing to apologize for, google doesn't find everything. As I said, you're taking a different approach anyway.

Here's a few links, one for my UDF and a project based on it. They are geared towards injecting compiled DLL code. But that code could be used to communicate back to a running AutoIt to conform to your framework.

Link to comment
Share on other sites

Thank you for the informations. I think this will help me a lot finding a better way to hook external functions. First I have to find a method without crashing Autoit too often and after that I must increase the speed of the hook... Hopefully you'll hear something new of me in the next monthes :)

mfg

Edited by CakeOfChaos
Link to comment
Share on other sites

  • 3 weeks later...

Mh was trying it with WinSocks but it fails all params seems to be 0 :S

#RequireAdmin
#include "Hooking.au3"
;===================>Global Variables
Global $hSendHook,$hRecvHook, $hProc
Global $pString[2] = [0, 0] ;the first element holds the address and the second the length, so its easier to call the _DelString() Function
Global $sProcessName = "test.exe" ;our target process
;===========>
#cs
int recv(
  __in   SOCKET s,
  __out  char *buf,
  __in   int len,
  __in   int flags
);
int send(
  __in  SOCKET s,
  __in  const char *buf,
  __in  int len,
  __in  int flags
);
#ce
SetPrivilege("SeDebugPrivilege", 1) ;too trivial
$recv = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("WS2_32.dll"), "recv") ;we are reading the address of recv in the RAM
$send = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("WS2_32.dll"), "send") ;we are reading the address of send in the RAM
;MsgBox("","",$lpMsgBoxA)
$recvcallback = DllCallbackRegister("_Recv", "int", "dword") ;we are registering the callback function
$sendcallback = DllCallbackRegister("_Send", "int", "dword") ;we are registering the callback function
If @error Then
    MsgBox(16, "ERROR", "Couldn't initialize Callback")
    Exit
EndIf
$recvptr = DllCallbackGetPtr($recvcallback)
$sendptr = DllCallbackGetPtr($sendcallback)
_VirtualProtect(Number($recvptr), 94) ;we have to unprotect the Callbackfunction
_VirtualProtect(Number($sendptr), 94) ;we have to unprotect the Callbackfunction
$hProc = _OpenProcess($sProcessName) ;we have to open the process
$hRecvHook = _SetHook(number($recv), 5, Number($recvptr ), "int;str;int;int", $hProc) ;we are going to hook the recv-Function
$hSendHook = _SetHook(number($send), 5, Number($sendptr), "int;str;int;int", $hProc) ;we are going to hook the send-Function
Do
    Sleep(1000)
until NOT ProcessExists($sProcessName) ;waiting

Func _Send($iParam)
;MsgBox("","","1: "&Hex($iParam))
_GetParameter($iParam, $hSendHook, $hProc)
MsgBox("","","Data: "&DllStructgetdata($hSendHook[5], 1))
Return 0
EndFunc
Func _Recv($iParam)
;MsgBox("","","1: "&Hex($iParam))
_GetParameter($iParam, $hRecvHook, $hProc)
;MsgBox("","","Data: "&DllStructgetdata($hRecvHook[5], 1))
Return 0
EndFunc
Link to comment
Share on other sites

The first Parameter is possibly the return address. I am not sure, but after Debugging I think so.

This is a working example:

#include "Hooking.au3"
;===================>Global Variables
Global $hHook, $hProc
Global $pString[2] = [0, 0] ;the first element holds the address and the second the length, so its easier to call the _DelString() Function
Global $sProcessName = "exploit_test.exe" ;our target process
;===========>
SetPrivilege("SeDebugPrivilege", 1) ;too trivial
$lpMsgBoxA = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("Ws2_32.dll"), "send") ;we are reading the address of MessageBoxA in the RAM
$callback = DllCallbackRegister("myHookFunc", "none", "dword") ;we are registering the callback function
If @error Then
MsgBox(16, "ERROR", "Couldn't initialize Callback")
Exit
EndIf
$ptr = DllCallbackGetPtr($callback)
_VirtualProtect(Number($ptr), 94) ;we have to unprotect the Callbackfunction
$hProc = _OpenProcess($sProcessName) ;we have to open the process
$hHook = _SetHook(number($lpMsgBoxA), 5, Number($ptr), "int;int;int;int", $hProc) ;we are going to hook the MessageBoxA-Function
Do
Sleep(1000)
until NOT ProcessExists($sProcessName) ;waiting
Func myHookFunc($iParam) ;=>our HookFunction
If $pString[0] <> 0 Then _DelString($pString[0], $pString[1], $hProc) ;free the old string
_GetParameter($iParam, $hHook, $hProc) ;get the parameter from the stack
ConsoleWrite("================NEW PAKET WILL BE SENDED==========" & @crlf)
For $i = 2 To 5
  ConsoleWrite($i & ". Argument is " & Number(DllStructgetdata($hHook[5], $i)) & @crlf)
next
;==============>String auslesen
$myString = _ReadString(DllStructgetdata($hHook[5], 3), $hproc)
Consolewrite("Gesendet wird: " & $myString &@crlf)
;===================>
_SetParameter($iParam, $hHook, $hProc) ;and write it ;)
return ;works much better with return
EndFunc
Link to comment
Share on other sites

  • 9 months later...

The first Parameter is possibly the return address. I am not sure, but after Debugging I think so.

This is a working example:

#include "Hooking.au3"
;===================>Global Variables
Global $hHook, $hProc
Global $pString[2] = [0, 0] ;the first element holds the address and the second the length, so its easier to call the _DelString() Function
Global $sProcessName = "exploit_test.exe" ;our target process
;===========>
SetPrivilege("SeDebugPrivilege", 1) ;too trivial
$lpMsgBoxA = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("Ws2_32.dll"), "send") ;we are reading the address of MessageBoxA in the RAM
$callback = DllCallbackRegister("myHookFunc", "none", "dword") ;we are registering the callback function
If @error Then
MsgBox(16, "ERROR", "Couldn't initialize Callback")
Exit
EndIf
$ptr = DllCallbackGetPtr($callback)
_VirtualProtect(Number($ptr), 94) ;we have to unprotect the Callbackfunction
$hProc = _OpenProcess($sProcessName) ;we have to open the process
$hHook = _SetHook(number($lpMsgBoxA), 5, Number($ptr), "int;int;int;int", $hProc) ;we are going to hook the MessageBoxA-Function
Do
Sleep(1000)
until NOT ProcessExists($sProcessName) ;waiting
Func myHookFunc($iParam) ;=>our HookFunction
If $pString[0] <> 0 Then _DelString($pString[0], $pString[1], $hProc) ;free the old string
_GetParameter($iParam, $hHook, $hProc) ;get the parameter from the stack
ConsoleWrite("================NEW PAKET WILL BE SENDED==========" & @crlf)
For $i = 2 To 5
ConsoleWrite($i & ". Argument is " & Number(DllStructgetdata($hHook[5], $i)) & @crlf)
next
;==============>String auslesen
$myString = _ReadString(DllStructgetdata($hHook[5], 3), $hproc)
Consolewrite("Gesendet wird: " & $myString &@crlf)
;===================>
_SetParameter($iParam, $hHook, $hProc) ;and write it ;)
return ;works much better with return
EndFunc

Guys,

I can intercept the send and recv, but how can I change them ("send" and "recv" packets) using as base this code.

I know it is hard, but this takes a lot of code.

Grtz!!

Link to comment
Share on other sites

  • 5 months later...
  • 7 months later...

Is it me or have you never understood the term "declare a variable"?

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

  • Developers

No, excuse me, but where should I just declare them in the NomadMemory or in the Hooking.au3? And should it be local or global?

The point is that you have no clue what you are doing and are trying to complete a marathon without having first learned to walk.

So, please start learning some basics before asking al these questions.

This question should be easy to answer by yourself after having spend a little time trying you understand what the script does.

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • 8 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...