Sign in to follow this  
Followers 0
FaridAgl

MessageBox in a separated thread with bytecodes

18 posts in this topic

#1 ·  Posted (edited)

First of all, please move this thread to a more suitable forum if it shouldn't be here.

I'm trying to create a MessageBox in a new thread with AutoIt. Logically it seems to be OK, as I'm using the byte codes to push data to the stack, and call the the MessageBoxA functions, but it crashes (As expected(!)).

Here it is:

#cs
    int WINAPI MessageBox(
    _In_opt_  HWND hWnd,
    _In_opt_  LPCTSTR lpText,
    _In_opt_  LPCTSTR lpCaption,
    _In_      UINT uType
    );
#ce

Global Const $CAPTION = "Caption"
Global Const $TEXT = "Text"

Global $tByteCodes = DllStructCreate("BYTE[20]")

DllStructSetData($tByteCodes, 1, 0x6A, 1) ;PUSH
DllStructSetData($tByteCodes, 1, 0x00, 2) ;uType

DllStructSetData($tByteCodes, 1, 0x68, 3) ;PUSH
DllStructSetData($tByteCodes, 1, 0x00, 4) ;OFFSET lpCaption
DllStructSetData($tByteCodes, 1, 0x00, 5)
DllStructSetData($tByteCodes, 1, 0x00, 6)
DllStructSetData($tByteCodes, 1, 0x00, 7)

DllStructSetData($tByteCodes, 1, 0x68, 8) ;PUSH
DllStructSetData($tByteCodes, 1, 0x00, 9) ;OFFSET lpText
DllStructSetData($tByteCodes, 1, 0x00, 10)
DllStructSetData($tByteCodes, 1, 0x00, 11)
DllStructSetData($tByteCodes, 1, 0x00, 12)

DllStructSetData($tByteCodes, 1, 0x6A, 13) ;PUSH
DllStructSetData($tByteCodes, 1, 0x00, 14) ;hWnd

DllStructSetData($tByteCodes, 1, 0xFF, 15) ;CALL
DllStructSetData($tByteCodes, 1, 0x15, 16)
DllStructSetData($tByteCodes, 1, 0x00, 17) ;DWORD PTR MessageBoxA
DllStructSetData($tByteCodes, 1, 0x00, 18)
DllStructSetData($tByteCodes, 1, 0x00, 19)
DllStructSetData($tByteCodes, 1, 0x00, 20)

Global $tCaption = DllStructCreate("CHAR[" & StringLen($CAPTION) + 1 & "]")
DllStructSetData($tCaption, 1, $CAPTION)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tCaption), 3, 2), 4)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tCaption), 5, 2), 5)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tCaption), 7, 2), 6)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tCaption), 9, 2), 7)

Global $tText = DllStructCreate("CHAR[" & StringLen($TEXT) + 1 & "]")
DllStructSetData($tText, 1, $TEXT)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tText), 3, 2), 9)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tText), 5, 2), 10)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tText), 7, 2), 11)
DllStructSetData($tByteCodes, 1, "0x" & StringMid(DllStructGetPtr($tText), 9, 2), 12)

Global $pUser32 = GetModuleHandle("user32.dll")
Global $pMessageBoxA = GetProcAddress($pUser32, "MessageBoxA")
DllStructSetData($tByteCodes, 1, "0x" & StringMid($pMessageBoxA, 3, 2), 20)
DllStructSetData($tByteCodes, 1, "0x" & StringMid($pMessageBoxA, 5, 2), 19)
DllStructSetData($tByteCodes, 1, "0x" & StringMid($pMessageBoxA, 7, 2), 18)
DllStructSetData($tByteCodes, 1, "0x" & StringMid($pMessageBoxA, 9, 2), 17)

ConsoleWrite(DllStructGetPtr($tByteCodes, 1) & @CRLF)

Global $dwThreadId
CreateThread(0, 0, DllStructGetPtr($tByteCodes, 1), 0, 0, $dwThreadId) ;It crashes here...

MsgBox(0, "", "Block the script, so it won't exit while the thread is running.")

#cs
    HMODULE WINAPI GetModuleHandle(
    _In_opt_  LPCTSTR lpModuleName
    );
#ce
Func GetModuleHandle($sModuleName)
    Return DllCall("kernel32.dll", "HANDLE", "GetModuleHandle", _
            "str", $sModuleName)[0]
EndFunc

#cs
    FARPROC WINAPI GetProcAddress(
    _In_  HMODULE hModule,
    _In_  LPCSTR lpProcName
    );
#ce
Func GetProcAddress($hModule, $sProcName)
    Return DllCall("kernel32.dll", "ptr", "GetProcAddress", _
            "HANDLE", $hModule, _
            "str", $sProcName)[0]
EndFunc

#cs
    HANDLE WINAPI CreateThread(
    _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_       SIZE_T dwStackSize,
    _In_       LPTHREAD_START_ROUTINE lpStartAddress,
    _In_opt_   LPVOID lpParameter,
    _In_       DWORD dwCreationFlags,
    _Out_opt_  LPDWORD lpThreadId
    );
#ce
Func CreateThread($pThreadAttributes, $dwStackSize, $pStartAddress, $pParameter, $dwCreationFlags, ByRef $dwThreadId)
    Local $tThreadId = DllStructCreate("DWORD")

    Local $avResult = DllCall("kernel32.dll", "BOOL", "CreateThread", _
            "ptr", $pThreadAttributes, _
            "DWORD", $dwStackSize, _
            "ptr", $pStartAddress, _
            "ptr", $pParameter, _
            "DWORD", $dwCreationFlags, _
            "ptr", DllStructGetPtr($tThreadId, 1))

    $dwThreadId = DllStructGetData($tThreadId, 1)
    Return $avResult[0]
EndFunc

#cs
    BOOL WINAPI CloseHandle(
    _In_  HANDLE hObject
    );
#ce
Func CloseHandle($hObject)
    Return DllCall("kernel32.dll", "BOOL", "CloseHandle", _
            "HANDLE", $hObject)[0]
EndFunc
Edited by D4RKON3

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Look this example:

#include <winapi.au3>
#include <Memory.au3>



$pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
$CodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)
$MessageBoxAddress = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("user32.dll"), "str", "MessageBoxW")
$MessageBoxAddress = $MessageBoxAddress[0]


$texto="hola Mundo"
$titulo="Titulo"

 Local $tDataBuffer = DllStructCreate("wchar texto[" & StringLen($texto) + 1 & "]")
Local $tDataBuffer2 = DllStructCreate("wchar titulo[" & StringLen($titulo) + 1 & "]")

    DllStructSetData($tDataBuffer, "texto", $texto)
    DllStructSetData($tDataBuffer2, "titulo", $titulo)


Local $Opcode
$Opcode &= "0x"
$Opcode &= "68" & SwapEndian(2)
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer2, 1))
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer, 1))
$Opcode &= "68" & SwapEndian(0)
$Opcode &= "B8" & SwapEndian($MessageBoxAddress)
$Opcode &= "FFD0"
$Opcode &= "C3"

DllStructSetData($CodeBuffer, 1, $Opcode)


;Local $Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0)

local $Ret=DllCallAddress("int",DllStructGetPtr($CodeBuffer))
Consolewrite(@CRLF  & $Ret[0] & @CRLF)

Msgbox(0,"","Normal Msgbox")

Func SwapEndian($hex)
    Return Hex(Binary($hex))
EndFunc   ;==>SwapEndian

It is not for beta version.

also let me say that Autoit is not safe threading as far as I know.

saludos

Edited by Danyfirex

Share this post


Link to post
Share on other sites

Thanks, that works now, the MessageBox runs in a separated thread and won't block the script execution.

Gonna make it cleaner and as simple as possible and post it in the Example Forum.

Thank you.

#include <winapi.au3>
#include <Memory.au3>



$pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
$CodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)
$MessageBoxAddress = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("user32.dll"), "str", "MessageBoxW")
$MessageBoxAddress = $MessageBoxAddress[0]


$texto="hola Mundo"
$titulo="Titulo"

 Local $tDataBuffer = DllStructCreate("wchar texto[" & StringLen($texto) + 1 & "]")
Local $tDataBuffer2 = DllStructCreate("wchar titulo[" & StringLen($titulo) + 1 & "]")

    DllStructSetData($tDataBuffer, "texto", $texto)
    DllStructSetData($tDataBuffer2, "titulo", $titulo)


Local $Opcode
$Opcode &= "0x"
$Opcode &= "68" & SwapEndian(2)
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer2, 1))
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer, 1))
$Opcode &= "68" & SwapEndian(0)
$Opcode &= "B8" & SwapEndian($MessageBoxAddress)
$Opcode &= "FFD0"
$Opcode &= "C3"
ConsoleWrite($Opcode & @CRLF)
DllStructSetData($CodeBuffer, 1, $Opcode)


;Local $Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0)

;~ local $Ret=DllCallAddress("int",DllStructGetPtr($CodeBuffer))
;~ Consolewrite(@CRLF  & $Ret[0] & @CRLF)

Global $dwThreadId
CreateThread(0, 0, DllStructGetPtr($CodeBuffer), 0, 0, $dwThreadId) ;It crashes here...
Msgbox(0,"","Normal Msgbox")

Func SwapEndian($hex)
    Return Hex(Binary($hex))
EndFunc   ;==>SwapEndian

Func CreateThread($pThreadAttributes, $dwStackSize, $pStartAddress, $pParameter, $dwCreationFlags, ByRef $dwThreadId)
    Local $tThreadId = DllStructCreate("DWORD")

    Local $avResult = DllCall("kernel32.dll", "BOOL", "CreateThread", _
            "ptr", $pThreadAttributes, _
            "DWORD", $dwStackSize, _
            "ptr", $pStartAddress, _
            "ptr", $pParameter, _
            "DWORD", $dwCreationFlags, _
            "ptr", DllStructGetPtr($tThreadId, 1))

    $dwThreadId = DllStructGetData($tThreadId, 1)
    Return $avResult[0]
EndFunc
1 person likes this

Share this post


Link to post
Share on other sites

Why do you want a message box in another thread? If you need you script to do things while a message is visible, why not just create a GUI that looks like a message box?

Share this post


Link to post
Share on other sites

There is actually an example of a non blocking messagebox in the helpfile. Did you know that? Works perfectly as well since you aren't using the return value from the msgbox (though since all these values fit into an exit code that could work as well).

It's under "Using AutoIt > Command Line Parameters".

Share this post


Link to post
Share on other sites

Mat,

I guess you mean spawning a new process? Am I correct?

If yes, that's the most wired solution and will be my last option.

Thanks by the way.

Richard,

There are so many situation which I would fall in need of a non-blocking standard MessageBox.

Yes, I can simulate the MessageBox by creating a my own window, buy that wouldn't be as nice(!) as the native MessageBox.

Also it will look different on different versions of Windows.

Thank you.

Share this post


Link to post
Share on other sites

Here's the function you want - MessageBoxIndirect. Use CreateThread to call it. Just make sure to wait for the box to display before freeing the memory where the parameters are stored, or it won't work right. I do think you'll lose the return code though.

Share this post


Link to post
Share on other sites

Maybe by this way was better.

#include <winapi.au3>
#include <Memory.au3>



$pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
$CodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)
$MessageBoxAddress = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("user32.dll"), "str", "MessageBoxW")
$MessageBoxAddress = $MessageBoxAddress[0]


$texto="hola Mundo"
$titulo="Titulo"

 Local $tDataBuffer = DllStructCreate("wchar texto[" & StringLen($texto) + 1 & "]")
Local $tDataBuffer2 = DllStructCreate("wchar titulo[" & StringLen($titulo) + 1 & "]")

    DllStructSetData($tDataBuffer, "texto", $texto)
    DllStructSetData($tDataBuffer2, "titulo", $titulo)


Local $Opcode
$Opcode &= "0x"
$Opcode &= "68" & SwapEndian(2)
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer2, 1))
$Opcode &= "68" & SwapEndian(DllStructGetPtr($tDataBuffer, 1))
$Opcode &= "68" & SwapEndian(0)
$Opcode &= "B8" & SwapEndian($MessageBoxAddress)
$Opcode &= "FFD0"
$Opcode &= "C3"
ConsoleWrite($Opcode & @CRLF)
DllStructSetData($CodeBuffer, 1, $Opcode)


;Local $Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0)

;~ local $Ret=DllCallAddress("int",DllStructGetPtr($CodeBuffer))
;~ Consolewrite(@CRLF  & $Ret[0] & @CRLF)

Global $dwThreadId

local $hThread=CreateThread(0, 0, DllStructGetPtr($CodeBuffer), 0, 0, $dwThreadId) ;It crashes here...


;for Wait
 _WinAPI_WaitForSingleObject($hThread, 0xFFFFFFFF)
 
 ;for get MessabeBox return value
Local $ReturnValue = _GetExitCodeThread($hThread)

Msgbox(0,"","Value= " & $ReturnValue)

Func SwapEndian($hex)
    Return Hex(Binary($hex))
EndFunc   ;==>SwapEndian


Func _GetExitCodeThread($thread)
Local $Dummy = DllStructCreate("uint")
Local $Call = DllCall("Kernel32.dll", "BOOL", "GetExitCodeThread", "handle", $thread, "ptr", DllStructGetPtr($Dummy))
Return Dec(Hex(DllStructGetData($Dummy, 1))) ; hack hack hack
EndFunc   ;==>_GetExitCodeThread

Func CreateThread($pThreadAttributes, $dwStackSize, $pStartAddress, $pParameter, $dwCreationFlags, ByRef $dwThreadId)
    Local $tThreadId = DllStructCreate("DWORD")

    Local $avResult = DllCall("kernel32.dll", "BOOL", "CreateThread", _
            "ptr", $pThreadAttributes, _
            "DWORD", $dwStackSize, _
            "ptr", $pStartAddress, _
            "ptr", $pParameter, _
            "DWORD", $dwCreationFlags, _
            "ptr", DllStructGetPtr($tThreadId, 1))

    $dwThreadId = DllStructGetData($tThreadId, 1)
    Return $avResult[0]
EndFunc

saludos

Share this post


Link to post
Share on other sites

That's OK, but you are waiting for the created thread in the script's main thread, now it has no difference with AutoIt's MsgBox, they both will block the execution of the script.

I came up with this:

MessageBox(0, "Text", "Caption", 0)
MsgBox(0, "", "")

Func MessageBox($hWnd, $sText, $sCaption, $uType)
    Local Static $tCaption = DllStructCreate("CHAR[" & StringLen($sCaption) & "]")
    DllStructSetData($tCaption, 1, "Caption")
    Local Static $pCaption = Hex(Binary((DllStructGetPtr($tCaption, 1))))

    Local $tText = DllStructCreate("CHAR[" & StringLen($sText) & "]")
    DllStructSetData($tText, 1, $sText)
    Local $pText = Hex(Binary((DllStructGetPtr($tText, 1))))

    Local $hUser32 = DllCall("kernel32.dll", "HANDLE", "GetModuleHandle", _
            "str", "user32.dll")[0]

    Local $pMessageBoxA = DllCall("kernel32.dll", "ptr", "GetProcAddress", _
            "HANDLE", $hUser32, _
            "str", "MessageBoxA")[0]

    Local $sOpcode = "0x"
    $sOpcode &= "68" & Hex(Binary(($uType))) ;push uType
    $sOpcode &= "68" & $pCaption ;push sCaption
    $sOpcode &= "68" & $pText ;push sText
    $sOpcode &= "68" & Hex(Binary(($hWnd))) ;push hWnd
    $sOpcode &= "B8" & Hex(Binary(($pMessageBoxA))) ;mov eax, MessageBoxA
    $sOpcode &= "FFD0" ;call eax
    $sOpcode &= "C3" ;ret

    Local $tOpcode = DllStructCreate("BYTE[28]")
    DllStructSetData($tOpcode, 1, $sOpcode)
    Local $pOpcode = DllStructGetPtr($tOpcode)

    Local $hThread = DllCall("kernel32.dll", "BOOL", "CreateThread", _
            "ptr", 0, _
            "DWORD", 0, _
            "ptr", $pOpcode, _
            "ptr", 0, _
            "DWORD", 0, _
            "ptr", 0)

    DllCall("kernel32.dll", "BOOL", "CloseHandle", _
            "HANDLE", $hThread)
EndFunc

It's working, but there is a problem.

All allocated memories which were allocated by DllStructCreate will be freed once the execution goes out side of the function's local scope, that will ruin everything but not every time!

I

t could be fixed by allocating the memory by a call to VirtualAlloc but handling the allocated memory for freeing in the feature won't be that easy so the memory leak is unavoidable.

A work around to this is to calling the VirtualAlloc function on a line starting with Local Static, so it won't be called in the next calls to our MessageBox function. We could consider a chunk of memory, for example 1024 bytes as our "once and for ever" MessageBox buffer.

There are other cleaner ways as well, which adds a Startup and a Shutdown function to our MessageBox, and requires some Global variables, but will enable us to handle the memory, and the return value of MessageBox as well (Getting the return value needs an additional call to another function for example, MessageBoxGetReturnValue).

Thanks for all the tips and helps, let me know if have any idea.

wraithdu, thanks for the tips about freeing the memory.

Why are you suggesting MessageBoxIndirect? I checked the MSDN, but I didn't understand its advantage over MessageBox.

Thank you. 

Share this post


Link to post
Share on other sites

what really do you want to do? I can understand. 

Share this post


Link to post
Share on other sites

I want to create a non blocking MessageBox, not a window that is created by me and looks like a MessageBox and not a child process that show a MessageBox.

"A non blocking standard MessageBox within the current process", that's what I'm seeking.

Share this post


Link to post
Share on other sites

You have it.

Freeing allocated memory can be done from within the other thread just before it's terminated.

And with MessageBoxIndirect you get working x64 version for free, that's the main difference.

1 person likes this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Damn, you are f**king right :|

I can easily call the VirtualFree from the thread.

Thanks a lot.

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Well, here is it:

MessageBox(0, "Text", "Caption", 0)
MsgBox(0, "", "")

Func MessageBox($hWnd, $sText, $sCaption, $uType)
    Local $dwOpcodeSize = 50
    Local $dwTextSize = StringLen($sText) + 1
    Local $dwCaptionSize = StringLen($sCaption) + 1
    Local $dwSize = $dwOpcodeSize + $dwTextSize + $dwCaptionSize

    Local $pAddress = VirtualAlloc(0, $dwSize, 0x00001000, 0x40) ;MEM_COMMIT, PAGE_EXECUTE_READWRITE
    Local $hProcess = GetCurrentProcess()
    Local $pText = $pAddress + $dwOpcodeSize
    Local $tText = DllStructCreate("CHAR[" & $dwTextSize & "]")
    DllStructSetData($tText, 1, $sText)
    WriteProcessMemory($hProcess, $pText, DllStructGetPtr($tText, 1), $dwTextSize)

    Local $pCaption = $pText + $dwTextSize
    Local $tCaption = DllStructCreate("CHAR[" & $dwCaptionSize & "]")
    DllStructSetData($tCaption, 1, $sCaption)
    WriteProcessMemory($hProcess, $pCaption, DllStructGetPtr($tCaption, 1), $dwCaptionSize)

    Local $pMessageBoxA = GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA")
    Local $pVirtualFree = GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualFree")

    Local $sOpcode = "0x"

    $sOpcode &= "68" & SwapEndian($uType) ;push uType
    $sOpcode &= "68" & SwapEndian($pCaption) ;push sCaption
    $sOpcode &= "68" & SwapEndian($pText) ;push sText
    $sOpcode &= "68" & SwapEndian($hWnd) ;push hWnd
    $sOpcode &= "B8" & SwapEndian($pMessageBoxA) ;mov eax, MessageBoxA
    $sOpcode &= "FFD0" ;call eax

    $sOpcode &= "68" & SwapEndian(0x8000) ;push MEM_RELEASE (dwFreeType)
    $sOpcode &= "68" & SwapEndian(0) ;push dwSize
    $sOpcode &= "68" & SwapEndian($pAddress) ;push pAddress
    $sOpcode &= "B8" & SwapEndian($pVirtualFree) ;mov eax, VirtualFree
    $sOpcode &= "FFD0" ;call eax

    $sOpcode &= "C3" ;ret

    Local $tOpcode = DllStructCreate("BYTE[50]")
    DllStructSetData($tOpcode, 1, $sOpcode)
    WriteProcessMemory($hProcess, $pAddress, DllStructGetPtr($tOpcode, 1), $dwOpcodeSize)

    Local $hThread = CreateThread(0, 0, $pAddress, 0, 0)
    CloseHandle($hThread)
EndFunc

Func VirtualAlloc($pAddress, $dwSize, $flAllocationType, $flProtect)
    Return DllCall("kernel32.dll", "ptr", "VirtualAlloc", _
            "ptr", $pAddress, _
            "DWORD", $dwSize, _
            "DWORD", $flAllocationType, _
            "DWORD", $flProtect)[0]
EndFunc

Func CreateThread($pThreadAttributes, $dwStackSize, $pStartAddress, $pParameter, $dwCreationFlags)
    Return DllCall("kernel32.dll", "HANDLE", "CreateThread", _
            "ptr", $pThreadAttributes, _
            "DWORD", $dwStackSize, _
            "ptr", $pStartAddress, _
            "ptr", $pParameter, _
            "DWORD", $dwCreationFlags, _
            "ptr", 0)[0]
EndFunc

Func CloseHandle($hObject)
    Return DllCall("kernel32.dll", "BOOL", "CloseHandle", _
            "HANDLE", $hObject)[0]
EndFunc

Func GetProcAddress($hModule, $sProcName)
    Return DllCall("kernel32.dll", "ptr", "GetProcAddress", _
            "HANDLE", $hModule, _
            "str", $sProcName)[0]
EndFunc

Func GetModuleHandle($sModuleName)
    Return DllCall("kernel32.dll", "HANDLE", "GetModuleHandle", _
            "str", $sModuleName)[0]
EndFunc

Func WriteProcessMemory($hProcess, $lpAddress, $lpBuffer, $nSize)
    Return DllCall("kernel32.dll", "BOOL", "WriteProcessMemory", _
            "HANDLE", $hProcess, _
            "ptr", $lpAddress, _
            "ptr", $lpBuffer, _
            "DWORD", $nSize, _
            "ptr", 0)[0]
EndFunc

Func SwapEndian($dwValue)
    Return Hex(Binary($dwValue))
EndFunc

Func GetCurrentProcess()
    Return DllCall("kernel32.dll", "HANDLE", "GetCurrentProcess")[0]
EndFunc

The idea was brilliant, but there is a little problem.

When VirtualFree gets called in the created thread, it frees the allocated memory. The problem is the 1 byte that we are really interesting in:

C3, the magical bytecode of ret. It won't be there anymore and that's why the process crashes right after clicking on a button of the created MessageBox.

Edited by D4RKON3

Share this post


Link to post
Share on other sites

I meant freeing strings, not the memory for executable code. For this you need two different calls to VirtualAlloc.

But if I were you I would switch to heap allocation, make one HeapAlloc and then call HeapFree from within the thread just before it returns. This way you can free all.

For this idea you wouldn't use default process heap because it's not executable type. First you would call HeapCreate specifying HEAP_CREATE_ENABLE_EXECUTE, then allocate all needed memory from that heap and later free it with HeapFree.

Heap object that you got by calling HeapCreate is your private object that you won't destroy before thread is finished executing.

 

You have few unnecessary complications in you current code. WriteProcessMemory is so clumsy :D, did you forget that DllStructCreate has two parameters?

Other thing is that your thread should return the return value of messagebox call, so maybe to save the value of eax to ebx (or whatever) before freeing memory and restore it from there before the thread returns.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Thank you, let's see what I can do.

About the WriteProcessMemory, I was trying to use CopyMemory first, but that failed everytime and I couldn't find out why.

I didn't used DllStructCreate's 2nd parameter, because I thought it will free the pointed memory just like the memory allocated by itself(!), now, that I think better, I see that makes no sense!

I was trying to save the return value of MessageBox, but I didn't know in which register it would be after the call to MessageBox, as you said it's in EAX, it can be retrieved now.

Thanks, I will post the result as soon as I'm done.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Maybe this Can't Help, but @trancexx means this:

Local $tOpcode = DllStructCreate("BYTE[50]",$pAddress) ;$pAddress is the pointer return from VirtualAlloc
DllStructSetData($tOpcode, 1, $sOpcode)
     ;with that is not nescesary use Copy memory functions

Edit:

I keep thinking in use GetExitCodeThread to get msgbox return value.

saludos

Edited by Danyfirex

Share this post


Link to post
Share on other sites

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
Sign in to follow this  
Followers 0