AHK 机器码(MCode)的制作

本文来至feiyue的分享!

最早从官网看到大神们在使用机器码(MCode)的时候,惊为天人,极为仰慕。
可惜一看介绍,需要先下载安装VC或者GCC,还有各种参数配置,总感觉很难,
因此很长时间都没有使用过。

后来慢慢尝试使用GCC,发现并不难,因为都是用命令行调用的,下载安装
GCC后根本不用配置,找到gcc.exe程序就可以在命令行使用了。
我推荐使用 TDM-GCC 64位版,可以在百度搜索 TDM-GCC 或在 官网 下载。

我成功地实现了自己写C语言代码并快速转化为机器码(MCode),真令人高兴。
比较了多种方法后,我把最简单的转化方式分享给大家,让大家也来使用机器码。

  1. ;===========================================
  2. ; AHK机器码生成器】 v2.0 By FeiYue
  3. ;
  4. ; 使用方法:
  5. ;
  6. ; 1、下载安装 TDM-GCC 64位版 到默认的安装目录,下载网址为:
  7. ; https://sourceforge.net/projects/tdm-gcc/files/latest/download
  8. ;
  9. ; 2、下载安装 TCC 32 64位版 AHK的目录,下载网址为:
  10. ; https://bellard.org/tcc/
  11. ;
  12. ; 3、选择C代码后,按【 Alt+C 】热键生成 GCC 编译的机器码,
  13. ; 或者按【 Ctrl+Alt+C 】热键生成 TCC 编译的机器码
  14. ;
  15. ;===========================================
  16. !c:: ; 选择C代码后用 GCC 编译
  17. ^!c:: ; 选择C代码后用 TCC 编译
  18. ClipSaved:=Clipboard
  19. Clipboard=
  20. Send {Ctrl Down}c{CtrlUp}
  21. ClipWait, 3
  22. s:=Clipboard, Clipboard:=ClipSaved
  23. if s=
  24. {
  25. MsgBox, 4096, Error, The contents of the copy are empty
  26. Exit
  27. }
  28. Loop, 2 {
  29. i:=A_Index-1
  30. hex:=A_ThisLabel="!c" ? Gcc(s,i) : Tcc(s,i)
  31. hex:=RegExReplace("xxx" hex, ".{1,50}", "`r`n . ""$0""")
  32. s%i%:=StrReplace(hex, ". ""xxx", (i ? "x64":"x32") ":=""")
  33. }
  34. MsgBox, 4096, MCode has been generated! (32 + 64)
  35. , % Clipboard:=s0 . s1
  36. . "`r`n MCode(MyFunc, A_PtrSize=8 ? x64:x32)"
  37. s:=s0:=s1:=""
  38. return
  39. Gcc(s, win64=0)
  40. {
  41. dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
  42. ;-----------------------------
  43. exe1=C:\TDM-GCC-64\bin\gcc.exe
  44. exe2=C:\TDM-GCC-64\bin\objcopy.exe
  45. ;-----------------------------
  46. IfNotExist, %exe1%
  47. {
  48. MsgBox, 4096, Tip, Can't Find %exe1% !
  49. return
  50. }
  51. FileDelete, % cpp:=dir "\5.c"
  52. FileDelete, % obj:=dir "\5.obj"
  53. FileDelete, % log:=dir "\5.log"
  54. FileDelete, % bin:=dir "\5.bin"
  55. FileAppend, %s%, %cpp%
  56. SplitPath, ComSpec, cmd
  57. Loop
  58. {
  59. Process, Exist, %cmd%
  60. if !(pid:=ErrorLevel)
  61. Break
  62. Process, Close, %pid%
  63. Process, WaitClose, %pid%, 3
  64. }
  65. arg:=(win64 ? "-m64":"-m32") . " -O2"
  66. RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
  67. ,, Hide
  68. IfNotExist, %obj%
  69. {
  70. FileRead, s, %log%
  71. FileDelete, %cpp%
  72. FileDelete, %log%
  73. MsgBox, 4096, Tip, C Compile Error`n`n%s%
  74. return
  75. }
  76. RunWait, "%exe2%" -j .text -O binary "%obj%" "%bin%",, Hide
  77. hex:=bin2hex(bin)
  78. FileDelete, %cpp%
  79. FileDelete, %obj%
  80. FileDelete, %log%
  81. FileDelete, %bin%
  82. return, hex
  83. }
  84. Tcc(s, win64=0)
  85. {
  86. dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
  87. ;-----------------------------
  88. exe1:=dir (win64 ? "\TCC-64\tcc.exe" : "\TCC-32\tcc.exe")
  89. ;-----------------------------
  90. IfNotExist, %exe1%
  91. {
  92. MsgBox, 4096, Tip, Can't Find %exe1% !
  93. return
  94. }
  95. ;-----------------------------
  96. add0=`n int _Flag0_%A_Now%() { return 0x11110000; } `n
  97. add1=`n int _Flag1_%A_Now%() { return 0x11111111; } `n
  98. add2=`n int _Flag2_%A_Now%() { return 0x11111111; } `n
  99. add3=`n int _Flag3_%A_Now%() { return 0x11111111; } `n
  100. s:=add0 . add1 . add2 . s . add3
  101. ;-----------------------------
  102. FileDelete, % cpp:=dir "\5.c"
  103. FileDelete, % obj:=dir "\5.obj"
  104. FileDelete, % log:=dir "\5.log"
  105. FileAppend, % StrReplace(s,"`r"), %cpp%
  106. SplitPath, ComSpec, cmd
  107. Loop
  108. {
  109. Process, Exist, %cmd%
  110. if !(pid:=ErrorLevel)
  111. Break
  112. Process, Close, %pid%
  113. Process, WaitClose, %pid%, 3
  114. }
  115. arg:=(win64 ? "-m64":"-m32") . " -O2"
  116. RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
  117. ,, Hide
  118. IfNotExist, %obj%
  119. {
  120. FileRead, s, %log%
  121. FileDelete, %cpp%
  122. FileDelete, %log%
  123. MsgBox, 4096, Tip, C Compile Error`n`n%s%
  124. return
  125. }
  126. hex:=bin2hex(obj)
  127. ;-----------------------------
  128. p1:=RegExMatch(hex,"i)B811111111.{0,2}?C3",r)
  129. p2:=InStr(hex,r,0,p1+1), p3:=InStr(hex,r,0,0)
  130. len:=p2-p1, i:=(r="B811111111C3") ? p2+len : p2+StrLen(r)
  131. hex:=(p1 and p2) ? SubStr(hex,i,p3-p2-len) : ""
  132. ;-----------------------------
  133. FileDelete, %cpp%
  134. FileDelete, %obj%
  135. FileDelete, %log%
  136. return, hex
  137. }
  138. bin2hex(obj)
  139. {
  140. ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  141. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  142. VarSetCapacity(bin,1024), VarSetCapacity(bin,0)
  143. FileRead, bin, *c %obj%
  144. size:=VarSetCapacity(bin), p:=&bin
  145. VarSetCapacity(hex, (2*size+1)*(1+!!A_IsUnicode))
  146. SetFormat, IntegerFast, % "H" (fmt:=A_FormatInteger)/0
  147. Loop, %size%
  148. hex.=SubStr(0x100+(*p++),-1)
  149. SetFormat, IntegerFast, %fmt%
  150. SetBatchLines, %bch%
  151. ListLines, %lls%
  152. return, hex
  153. }
  154. MCode(ByRef code, hex)
  155. {
  156. ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  157. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  158. VarSetCapacity(code, len:=StrLen(hex)//2)
  159. Loop, % len
  160. NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
  161. DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
  162. SetBatchLines, %bch%
  163. ListLines, %lls%
  164. }
  165. ;

下面是一个AHK机器码(MCode)调用WinAPI的例子:

  1. /****** C source code ******
  2. #include <windows.h>
  3. typedef int (WINAPI * _MessageBoxA)(
  4. HWND hWnd,
  5. LPCSTR lpText,
  6. LPCSTR lpCaption,
  7. UINT uType
  8. );
  9. typedef BOOL (WINAPI * _GetUserNameA)(
  10. LPSTR lpBuffer,
  11. LPDWORD pcbBuffer
  12. );
  13. typedef void * (WINAPI * _GetWinAPI)(char * str);
  14. int WINAPI TestWinAPI(_GetWinAPI GetWinAPI, char * name, int * size)
  15. {
  16. char str1[] = "User32.dll\\MessageBoxA";
  17. _MessageBoxA MessageBoxA = (_MessageBoxA)GetWinAPI(str1);
  18. if (NULL == MessageBoxA)
  19. return -1;
  20. char str2[] = "Advapi32.dll\\GetUserNameA";
  21. _GetUserNameA GetUserNameA = (_GetUserNameA)GetWinAPI(str2);
  22. if (NULL == GetUserNameA)
  23. return -2;
  24. char text[] = "Hello World!";
  25. char title[] = "Machine Code Call WinAPI";
  26. MessageBoxA(0, text, title, 1);
  27. GetUserNameA(name, size);
  28. MessageBoxA(0, name, title, 1);
  29. return 0;
  30. }
  31. */
  32. if (!MyFunc)
  33. {
  34. x32:="5557BA78410000565383EC7C8D4424268BB424900000008"
  35. . "BBC2494000000C744242655736572C744242A33322E64C7442"
  36. . "42E6C6C5C4DC744243265737361C74424366765426F6689542"
  37. . "43AC644243C00890424FFD683EC0485C00F840301000089C3B"
  38. . "841000000C744245641647661668944246E8D442456C744245"
  39. . "A70693332C744245E2E646C6CC74424625C476574C74424665"
  40. . "5736572C744246A4E616D65890424FFD683EC0485C089C60F8"
  41. . "4BE0000008D6C243D8D442419C744241948656C6CC744241D6"
  42. . "F20576FC7442421726C6421C644242500C744243D4D616368C"
  43. . "7442441696E6520C7442445436F6465C74424492043616CC74"
  44. . "4244D6C205769C74424516E415049C644245500C744240C010"
  45. . "00000896C240889442404C7042400000000FFD383EC108B842"
  46. . "498000000893C2489442404FFD683EC08C744240C010000008"
  47. . "96C2408897C2404C7042400000000FFD331C083EC1083C47C5"
  48. . "B5E5F5DC20C00B8FFFFFFFFEBEF8DB600000000B8FEFFFFFFE"
  49. . "BE2909090909090909090"
  50. x64:="4154555756534881EC9000000048B85573657233322E644"
  51. . "8894424304889D748B86C6C5C4D65737361BA784100004889C"
  52. . "E4D89C44889442438C74424406765426F488D4C24306689542"
  53. . "444C644244600FFD64885C04889C30F84E200000048B841647"
  54. . "66170693332488D4C2470488944247048B82E646C6C5C47657"
  55. . "4488944247848B8557365724E616D654889842480000000B84"
  56. . "10000006689842488000000FFD64885C04889C60F84A200000"
  57. . "048B848656C6C6F20576F488D6C245041B9010000004889442"
  58. . "42048B84D616368696E6520488D542420488944245048B8436"
  59. . "F64652043616C4989E8488944245848B86C2057696E4150493"
  60. . "1C9C7442428726C6421C644242C004889442460C644246800F"
  61. . "FD34C89E24889F9FFD641B9010000004989E84889FA31C9FFD"
  62. . "331C04881C4900000005B5E5F5D415CC30F1F440000B8FFFFF"
  63. . "FFFEBE6660F1F840000000000B8FEFFFFFFEBD690909090909"
  64. . "0909090"
  65. MCode(MyFunc, A_PtrSize=8 ? x64:x32)
  66. GetWinAPI:=RegisterCallback("GetWinAPI","Fast")
  67. }
  68. VarSetCapacity(str,100,0), size:=100
  69. DllCall(&MyFunc, "Ptr",GetWinAPI, "Ptr",&str, "int*",size)
  70. MsgBox, 1, AHK Command
  71. , % "UserName:`t" StrGet(&str,"CP0") "`nSize:`t`t" size
  72. return
  73. GetWinAPI(pstr) ; 参数格式为:DLL文件名\\函数名
  74. {
  75. static WinAPI:=[]
  76. if (addr:=WinAPI[ v:=StrGet(pstr,"CP0") ])
  77. return, addr
  78. i:=InStr(v,"\",0,0), v1:=SubStr(v,1,i-1), v2:=SubStr(v,i+1)
  79. if !(base:=DllCall("LoadLibrary", "Str",v1, "Ptr"))
  80. return, 0
  81. if !(addr:=DllCall("GetProcAddress", "Ptr",base, "AStr",v2, "Ptr"))
  82. return, 0
  83. WinAPI[v]:=addr
  84. return, addr
  85. }
  86. MCode(ByRef code, hex)
  87. {
  88. ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  89. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  90. VarSetCapacity(code, len:=StrLen(hex)//2)
  91. Loop, % len
  92. NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
  93. DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
  94. SetBatchLines, %bch%
  95. ListLines, %lls%
  96. }
  97. ;

利用TCC动态运行C语言代码的简单方式:
(必须在AHK目录下安装 “\TCC-64\tcc.exe” 和 “\TCC-32\tcc.exe”)

  1. ;------------------------------------------
  2. ; Using TCC to run C code (By FeiYue)
  3. ;------------------------------------------
  4. Goto, F1
  5. F1::
  6. code=
  7. (
  8. //////////////
  9. char * __attribute__((stdcall)) hello(char * out) {
  10. char str[]="Hello World!";
  11. for (int i=0; str[i]!='\0'; i++)
  12. out[i]=str[i];
  13. return out;
  14. }
  15. //////////////
  16. )
  17. VarsetCapacity(str,100,0)
  18. MsgBox, 4096,, % StrGet( DllCall(TccRun(code), "ptr",&str, "ptr"), "CP0")
  19. return
  20. ;========== TCC Functions ==========
  21. TccRun(s)
  22. {
  23. static Address:=[]
  24. if (addr:=Address[hash:=GetHash(s)])
  25. return, addr
  26. if !(hex:=Tcc(s, A_PtrSize=8))
  27. return
  28. if !(addr:=DllCall("GlobalAlloc", "int",0, "ptr",len:=StrLen(hex)//2, "ptr"))
  29. return
  30. MCode(code,hex), DllCall("RtlMoveMemory", "ptr",addr, "ptr",&code, "ptr",len)
  31. DllCall("VirtualProtect", "ptr",addr, "ptr",len, "uint",0x40, "ptr*",0)
  32. Address[hash]:=addr
  33. return, addr
  34. }
  35. GetHash(s)
  36. {
  37. ListLines, % "Off" (lls:=A_ListLines!=0 ? "On":"Off")/0
  38. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  39. hash1:=hash2:=hash3:=0, size:=VarSetCapacity(s,-1), p:=&s
  40. Loop, % size
  41. v:=*p++
  42. , hash1:=(hash1*31 +v)&0xFFFFFFFF
  43. , hash2:=(hash2*131 +v)&0xFFFFFFFF
  44. , hash3:=(hash3*1313+v)&0xFFFFFFFF
  45. SetBatchLines, %bch%
  46. ListLines, %lls%
  47. return, hash1 "-" hash2 "-" hash3
  48. }
  49. Tcc(s, win64=0)
  50. {
  51. dir:=A_IsCompiled ? A_ScriptDir : RegExReplace(A_AhkPath,"\\[^\\]+$")
  52. ;-----------------------------
  53. exe1:=dir (win64 ? "\TCC-64\tcc.exe" : "\TCC-32\tcc.exe")
  54. ;-----------------------------
  55. IfNotExist, %exe1%
  56. {
  57. MsgBox, 4096, Tip, Can't Find %exe1% !
  58. return
  59. }
  60. ;-----------------------------
  61. add0=`n int _Flag0_%A_Now%() { return 0x11110000; } `n
  62. add1=`n int _Flag1_%A_Now%() { return 0x11111111; } `n
  63. add2=`n int _Flag2_%A_Now%() { return 0x11111111; } `n
  64. add3=`n int _Flag3_%A_Now%() { return 0x11111111; } `n
  65. s:=add0 . add1 . add2 . s . add3
  66. ;-----------------------------
  67. FileDelete, % cpp:=dir "\5.c"
  68. FileDelete, % obj:=dir "\5.obj"
  69. FileDelete, % log:=dir "\5.log"
  70. FileAppend, % StrReplace(s,"`r"), %cpp%
  71. SplitPath, ComSpec, cmd
  72. Loop
  73. {
  74. Process, Exist, %cmd%
  75. if !(pid:=ErrorLevel)
  76. Break
  77. Process, Close, %pid%
  78. Process, WaitClose, %pid%, 3
  79. }
  80. arg:=(win64 ? "-m64":"-m32") . " -O2"
  81. RunWait, %ComSpec% /c ""%exe1%" %arg% -c -o "%obj%" "%cpp%" 2>"%log%""
  82. ,, Hide
  83. IfNotExist, %obj%
  84. {
  85. FileRead, s, %log%
  86. FileDelete, %cpp%
  87. FileDelete, %log%
  88. MsgBox, 4096, Tip, C Compile Error`n`n%s%
  89. return
  90. }
  91. hex:=bin2hex(obj)
  92. ;-----------------------------
  93. p1:=RegExMatch(hex,"i)B811111111.{0,2}?C3",r)
  94. p2:=InStr(hex,r,0,p1+1), p3:=InStr(hex,r,0,0)
  95. len:=p2-p1, i:=(r="B811111111C3") ? p2+len : p2+StrLen(r)
  96. hex:=(p1 and p2) ? SubStr(hex,i,p3-p2-len) : ""
  97. ;-----------------------------
  98. FileDelete, %cpp%
  99. FileDelete, %obj%
  100. FileDelete, %log%
  101. return, hex
  102. }
  103. bin2hex(obj)
  104. {
  105. ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  106. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  107. VarSetCapacity(bin,1024), VarSetCapacity(bin,0)
  108. FileRead, bin, *c %obj%
  109. size:=VarSetCapacity(bin), p:=&bin
  110. VarSetCapacity(hex, (2*size+1)*(1+!!A_IsUnicode))
  111. SetFormat, IntegerFast, % "H" (fmt:=A_FormatInteger)/0
  112. Loop, %size%
  113. hex.=SubStr(0x100+(*p++),-1)
  114. SetFormat, IntegerFast, %fmt%
  115. SetBatchLines, %bch%
  116. ListLines, %lls%
  117. return, hex
  118. }
  119. MCode(ByRef code, hex)
  120. {
  121. ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  122. SetBatchLines, % "-1" (bch:=A_BatchLines)/0
  123. VarSetCapacity(code, len:=StrLen(hex)//2)
  124. Loop, % len
  125. NumPut("0x" SubStr(hex,2*A_Index-1,2),code,A_Index-1,"uchar")
  126. DllCall("VirtualProtect","ptr",&code,"ptr",len,"uint",0x40,"ptr*",0)
  127. SetBatchLines, %bch%
  128. ListLines, %lls%
  129. }
  130. ;
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
其他教程

Excel数据拆分发邮件

2020-3-27 20:26:21

其他教程

后台发送按键和操作鼠标 By FeiYue

2020-4-1 12:59:38

0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
私信列表
搜索