Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

MCode function + onlinegenerator (x86 and x64)


  • Please log in to reply
33 replies to this topic
Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Original Thread (German/Deutsch):

http://www.autohotke...or-x86-und-x64/

 

Hi,

I have tried to play around with MCode, but i have recognized that most of the old scripts does'nt work anymore.

So i decided to make a rewrite of the old scripts and try to improve what's possible.

 

The Features are:

- The MCode function automaticly selects between x86 and x64

- VirtualProtect (execution permission) for x64 (there are problems in most of all old scripts)

- The MCode can be encoded in HEX or Base64

- Fast decoding functions

- Online generator

 

Requirements:

- Windows XP, Windows 2003 or newer

- AutoHotkey 1.1+

 

You can find the online generator here:

http://bentschi.no-ip.org/mcode/

 

And here the new MCode function:

MCode(mcode)
{
  static e := {1:4, 2:1}, c := (A_PtrSize=8) ? "x64" : "x86"
  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
    return
  if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
    return
  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
  if (c="x64")
    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
  if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
    return p
  DllCall("GlobalFree", "ptr", p)
}

Example: (the compiled startcode from the generator)

MyFunction := MCode("2,x86:aipYww==,x64:uCoAAADD")
MsgBox, % DllCall(MyFunction, "cdecl")

 



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

wow this is good work

is there any way to make it backward compatible with the old MCode?



Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

One way would be...

oldmcode := "..." ;paste the MCode here!
function := MCode("1,x86:" oldmcode)
MsgBox, % DllCall(function, "cdecl")


guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
great, so if i just use HEX and X86 then i can use your generator as an online replacement for the old MCodeGen and use the output in the old MCode func

also
what is the "1" or "2" at the start of your MCode for?

Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

1 = HEX
2 = Base64
... only the way it is parsed.
 
My code looks like...

<encoding>[,x86:<x86_mcode>][,x64:<x64_mcode>]

... where ... is:
<> = description
[] = optional

 

encoding = 1:HEX, 2:Base64

x86_mcode = The decoded MCode for x86 (optional)

x64_mcode = The decoded MCode for x64 (optional)



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

- VirtualProtect (execution permission) for x64 (there are problems in most of all old scripts)

1. can you explain what problems? is it only problems with AHKx64? or with x64 cpu/windows ?
 

Example: (the compiled startcode from the generator)

MyFunction := MCode("2,x86:aipYww==,x64:uCoAAADD")
MsgBox, % DllCall(MyFunction, "cdecl")


2. the old MCode required you to call the func thru DllCall by address &
DllCall(&MyFunction, "cdecl")
i'm not understanding why yours doesnt

3. finally, i'm having problems with the 'for speed' version of the code. its not working. but the 'for size' is. you can run this string search example:
   haystack := "This is a very long string that takes up some memory. The quick brown fox jumps over the lazy dog. The sky isn't really blue."
   hLen := StrLen(haystack)
   needle := "lazy"
   nLen := StrLen(needle)

   forspeed := MCode("
(LTrim Join
1,x86:53558b6c24105633d25785ed7e318b7424208b7c241c8b5c24148d9b00000033c085f67e108d0c108a0c193a0c3875
05403bc67cf03bc6740d423bd57ce15f5e5d83c8ff5bc35f5e5d8bc25bc3
)")
   result := DllCall(forspeed, "UInt", &haystack, "UInt", hLen, "UInt", &needle, "UInt", nLen, "cdecl int")
   msgbox, % "forspeed = " result "`nerrorlevel = " ErrorLevel

   forsize := MCode("
(LTrim Join
1,x86:558bec33c95357394d0c7e298b7d108b5d0833d23b55147d148d040a8a04183a043a7506423b55147cef3b5514740d
413b4d0c7cdd83c8ff5f5b5dc38bc1ebf8
)")
   result := DllCall(forsize, "UInt", &haystack, "UInt", hLen, "UInt", &needle, "UInt", nLen, "cdecl int")
   msgbox, % "forsize = " result "`nerrorlevel = " ErrorLevel

return


MCode(mcode)
{
  static e := {1:4, 2:1}, c := (A_PtrSize=8) ? "x64" : "x86"
  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
    return
  if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
    return
  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
  if (c="x64")
    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
  if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
    return p
  DllCall("GlobalFree", "ptr", p)
}
C code used:
int match(char text[], int text_length, char pattern[], int pattern_length) {
  int i, j;
  for (i=0; i<text_length; i++)
  {
      for (j=0; j<pattern_length; j++)
      {
          if(text[i+j] != pattern[j])
          {
              break;
          }
      }
      if (j == pattern_length)
          return i;
  }
  return -1;
}
on the DllCall help page, it says that ErrorLevel 0xC0000005 means "access violation"
above code was run using AHK_L 32bit Ansi on 64bit win7. if it was a 64bit issue, shouldn't both MCodes fail? and not just one?

Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Ok, thanks.

 

I've tested it myself and you are right.

The "optimize for size" does not work for x86 (but on x64).

Now i have removed this option in the generator.

Thanks.



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
the thing is, it does work for the basic example "return 42" code that you give. i dont think you should remove the option. i would rather you not remove it, since it allows me to test both versions

maybe its just a problem with this particular C code

Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

I also had problems using code that uses char * or something similar.

Maybe this was the reason.

 

I have "maxspeed" enabled again under http://bentschi.no-i...code/index2.php

You can also view my code under http://bentschi.no-i...e/mcodegen2.ahk



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
thanks a lot man

guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

I have "maxspeed" enabled again under http://bentschi.no-i...code/index2.php

i tried to use "optimize for speed" but it failed with "Nice try!!!"

i think when you click the "Create machine code" button, it still passes the values through to index.php, not index2.php

guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
i posted a support thread that might be related, this time the problem is with the 'optimize for size' code, which means i cannot use the generator at all sad.png

http://www.autohotke...array-question/

edit/

it looks like TheGood's code is now offline. however, i found RSeding's version here:
http://www.autohotke...mcode/?p=449715

he is using the command line switch /Ox for optimization, and it seems to work for everything i've tried. i see that you are using /O1 and /O2. perhaps you should switch to /Ox, and also have the option to do no optimization with /Od

Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Thank you,

I've added the following optimization values to http://bentschi.no-i...code/index2.php

- Default (/Ox)

- None (/Od)

Also fixed it that index2.php really outputs in index2.php

 

"Nice try" means that the value is not allowed.

I added this, because otherwise it would be possible to inject PHP-Code to my computer.



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
thanks Bentschi, thats great, i think its a great idea to have all optimization levels as options

... however none of them work right now happy.png

you can test with my example C code in the topic i mentioned. all of your 'optimize' options are giving the same hexcode, and none of them work.

Lexikos has replied to my topic and he thinks that the /O1 optimization is working correctly, but that perhaps your generator is parsing the code.cod file and truncating out zeroes.

i have just tested with the offline MCodeGen and that is the case for me too. i think the problem has to do with your parsing of the asm output. you could check RSeding's version of MCodeGen that i linked above, that seems to have different regex than what you're using

Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008

Update:

- fixed parse-errors in the generator (thanks guest3456 and Lexicos)

- Added Optimization "None" and "Default" in the generator

 

i've removed index2.php and replaced index.php with it.

Now the working generator is at http://bentschi.no-ip.org/mcode/ like before