What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » Call ASM routine from your script (with example)

Call ASM routine from your script (with example)
Author: Message:
CookieRevised
Elite Member
*****

Avatar

Posts: 15517
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
O.P. Call ASM routine from your script (with example)
There are times that you have a binary string inside a (Plus!) DataBloc.
Now, there is a problem if you want to output that binary data for example in the debug window of your script, or if you want to manipulate it further in your script as being a normal string.

This because the ReadString() method will only read up until the first Null character ("\0"); and a binary string can of course contain much more data after a Null character.

You also can't use the ReadBSTR() method directly, because that binary string isn't a BSTR string (a BSTR is a unicode string prefixed with its length, thus, allowing for Null characters). Even if you would add the known length of that binary string in front of it, you still would need to convert it to 'pseudo' unicode first to be able to read it using ReadBSTR().

'pseudo' because all you need to do is add a Null byte (0x0) after each byte in the binary string. It isn't really unicode unicode in that way, but it can be read using unicode read functions like ReadBSTR().

You could use some Unicode conversation APIs for that (eg: MultiByteToWideChar API). But the problem with that is that those APIs will actually change some of the bytes into another byte + not a Null character; they actaully map the characters according to a 'code page', they do not simply append a Null byte after each byte. Aka they have the very real potential to mangle up the real data from the binary string and thus producing the wrong output.

In the end, what you probably end up with is something like this:
js code:
// BinaryData is a DataBloc containing bytes
// OutputString is going to be a BSTR, so we can output it using ReadBSTR()

var OutputString = Interop.Allocate(BinaryData.Size * 2 + 4 + 2);
// *2 because it contains a unicode string
// +4 to accomodate for the DWORD length
// +2 for the unicode termination Null character

// Add the size of the string into the first DWORD of the BSTR
OutputString.WriteDWORD(0, BinaryData.Size * 2);

>>>// Convert the binary DataBloc into a pseudo unicode string (aka append a Null character after each byte)<<<
>>>for (var i=0; i < BinaryData.Size; i++) {<<<
>>>    OutputString.SetAt(i * 2 + 4, BinaryData.GetAt(i));<<<
>>>}<<<

// Read out the BSTR string and output it
Debug.Trace(OutputString.ReadBSTR(0));

Now, this will work, but it will be dead slow. So, in many cases it is realy useless. For example, think about outputting a memory dump of 10000 bytes with the above code. But what if we can replace that slow loop function with assembler code (you can't go any faster than that)? Wouldn't that be cool? Well, you can:

js code:
// BinaryData is a DataBloc containing bytes
// OutputString is going to be a BSTR, so we can output it using ReadBSTR()

var OutputString = Interop.Allocate(BinaryData.Size * 2 + 4 + 2);
// *2 because it contains a unicode string
// +4 to accomodate for the DWORD length
// +2 for the unicode termination Null character

// Add the size of the string into the first DWORD of the BSTR
OutputString.WriteDWORD(0, BinaryData.Size * 2);

>>>// Create our ASM routine<<<
>>>// It takes the memory pointer to a byte array as input and copies the individual bytes to the memory offset given in the second paramater,<<<
>>>// but each time increasing the memory offset by two (instead of by one). Thus essentially doubling its size. eg: \1\2\3 is copied as \1\0\2\0\3\0.<<<
>>>var sASM = "\u8B55\u244C\u8B10\u2454\u8B0C\u246C\u6608\uB60F\u0045\u8966\u4502\u4242\uF3E2\uC25D\u0010";<<<
>>>var oASM = Interop.Allocate(sASM.length * 2 + 2);<<<
>>>oASM.WriteString(0, sASM);<<<

>>>// Call the mighty ASM routine<<<
>>>// Here the 'magic' happens; we (ab)use the CallWindowProc API.<<<
>>>Interop.Call("User32", "CallWindowProcW", oASM.DataPtr, BinaryData.DataPtr, OutputString.DataPtr + 4, BinaryData.Size, null);<<<

// Read out the BSTR string and output it
Debug.Trace(OutputString.ReadBSTR(0));
This code will run as good as instantly because of the used ASM:
js code:
/*
      HEX             ASM
0000  55              push    ebp            ; save old frame pointer
0001  8B 4C 24 10     mov     ecx, [esp+10h] ; copy value of parameter 3 (=length of input string) into counter register (CX)
0005  8B 54 24 OC     mov     edx, [esp+0Ch] ; copy value of parameter 2 (=mem adress of output string) into data register (DX)
0009  8B 6C 24 08     mov     ebp, [esp+8]   ; copy value of parameter 1 (=mem adress of input string) into base pointer register (BP)
                      'start':
000D  66 0F B6 45 00  movzx   ax, byte ptr [ebp+0] ; copy byte value from mem adress stored in EBP to AX
0012  66 89 02        mov     [edx], ax      ; copy AX to mem adress stored in EDX
0015  45              inc     ebp            ; increment EBP
0016  42              inc     edx            ; increment EDX
0017  42              inc     edx            ; increment EDX
0018  E2 F3           loop    'start'        ; decrement ECX and jump to 'start' if CX!=0
001A  5D              pop     ebp            ; restore old frame pointer
001B  C2 10           retn    10h            ; end
*/

---------

EDIT:

Apparently there was already another nice example of using ASM in scripting, created by Mnjul some time ago here (note: thread is in beta testing section, so only beta testers can access it) and Matty used it to create this script.

The principle is just the same: write the ASM code and use the opcodes (=the hexadecimal values) to make a binary data string and place that in memory.

His script uses the WriteProcessMemory API to inject (asm) code into the process memory (but not yet run it!), rerouting the default call to the WinProc procedure to this code instead, and calling the 'old' WinProc procedure after the new injected code has finished.

This post was edited on 05-02-2011 at 08:27 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
05-02-2011 07:21 AM
Profile PM Find Quote Report
« Next Oldest Return to Top Next Newest »

Messages In This Thread
Call ASM routine from your script (with example) - by CookieRevised on 05-02-2011 at 07:21 AM
RE: Call ASM routine from your script (with example) - by SmokingCookie on 05-02-2011 at 01:46 PM
RE: RE: Call ASM routine from your script (with example) - by CookieRevised on 05-02-2011 at 05:17 PM
RE: Call ASM routine from your script (with example) - by SmokingCookie on 05-02-2011 at 06:45 PM
RE: RE: Call ASM routine from your script (with example) - by segosa on 05-02-2011 at 07:07 PM
RE: Call ASM routine from your script (with example) - by CookieRevised on 05-02-2011 at 07:07 PM
RE: Call ASM routine from your script (with example) - by matty on 05-02-2011 at 07:07 PM
RE: Call ASM routine from your script (with example) - by SmokingCookie on 05-02-2011 at 07:18 PM
RE: Call ASM routine from your script (with example) - by CookieRevised on 05-02-2011 at 08:04 PM
RE: Call ASM routine from your script (with example) - by Mnjul on 05-03-2011 at 01:00 AM
RE: Call ASM routine from your script (with example) - by whiz on 05-04-2011 at 07:25 AM


Threaded Mode | Linear Mode
View a Printable Version
Send this Thread to a Friend
Subscribe | Add to Favorites
Rate This Thread:

Forum Jump:

Forum Rules:
You cannot post new threads
You cannot post replies
You cannot post attachments
You can edit your posts
HTML is Off
myCode is On
Smilies are On
[img] Code is On